locked
Run a Private Sub procedure every 5 minutes RRS feed

  • Question

  • In VB.net I would like to run a Private Sub procedure in the background every 5 minutes.  How can I do that?


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 3:18 PM

Answers

  • Hi

    The BackGroundWorker is running on a different thread and so, you don't have direct access to the main thread (where your Label/TextBox is).

    So, try changing your line to

    Invoke(Sub() ClientTotal.Text = Convert.ToInt32(Command1.ExecuteScalar)


    Regards Les, Livingston, Scotland


    • Edited by leshay Wednesday, September 2, 2020 9:33 PM
    • Marked as answer by Jeff07 Wednesday, September 2, 2020 9:44 PM
    Wednesday, September 2, 2020 9:33 PM

All replies

  • Hello,

    I like using System.Threading.Timer rather than the Windows Timer as it' more flexible.

    A very simple example to run every 5 seconds. Rather than adding items to the ListBox you perform work you want to do.

    Form code, two buttons, one text box, one ListBox. Note there is a start and stop for the timer.

    Imports System.Runtime.CompilerServices
    Imports System.Threading
    Imports Timer = System.Threading.Timer
    Public Class Form1
        Private _mServiceTimer As Timer
        Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
            Start()
        End Sub
        Private Sub Start()
            Dim value As Integer
            If Integer.TryParse(IntervalTextBox.Text, value) Then
    
            End If
            _mServiceTimer = New Timer(AddressOf Dispatcher)
            _mServiceTimer.Change(value, Timeout.Infinite)
        End Sub
    
        Private Sub Dispatcher(e As Object)
            ListBox1.InvokeIfRequired(Sub(listBox) listBox.Items.Add($"{Now.ToString("hh:mm:ss")}"))
            _mServiceTimer.Dispose()
            Start()
        End Sub
    
        Private Sub StopButton_Click(sender As Object, e As EventArgs) Handles StopButton.Click
            _mServiceTimer.Dispose()
        End Sub
    End Class
    ''' <summary>
    ''' Place in a code module file
    ''' </summary>
    Public Module ControlExtensions
    
        <Extension>
        Public Function InvokeIfRequired(Of T As Control)(control As T, action As Action(Of T)) As IAsyncResult
    
            If control.InvokeRequired Then
                Try
    
                    Return control.BeginInvoke(
                        New Action(Of T, Action(Of T))(AddressOf InvokeIfRequired),
                        New Object() {control, action})
    
                Catch ex As Exception
    
                    Return Nothing
    
                End Try
            Else
    
                action(control)
                Return Nothing
    
            End If
    
        End Function
    End Module
    
    Can it be simpler, sure with a Windows Timers but as stated above this is what I recommend. 


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, September 2, 2020 3:48 PM
  • Thank you for the fast reply and I will try it out and get back to you.

    Jeff


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 3:57 PM
  • What kind of accuracy are you looking for?  5 minutes ± ??????

    Search Documentation

    SerialPort Info

    Multics - An OS ahead of its time.

     "Those who use Application.DoEvents have no idea what it does

        and those who know what it does never use it."    former MSDN User JohnWein

    Wednesday, September 2, 2020 4:12 PM
  • Thank you for the fast reply and I will try it out and get back to you.

    Jeff


    ISV using VB.net and SQL Server

    Note I did time in five seconds intervals as it's easier to see it working rather than wait five minutes.

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, September 2, 2020 4:16 PM
  • Hi

    Here is a version using a regular Timer and a BackGroundWorker. This example doesn't need any controls in the Designer.

    Option Strict On
    Option Explicit On
    Imports System.ComponentModel
    Public Class Form1
    	Dim WithEvents MyTimer As New Timer
    	Dim WithEvents MyBGW As New BackgroundWorker
    	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    		With MyTimer
    			.Interval = 5 * 60 * 1000
    			.Enabled = True
    		End With
    	End Sub
    	Private Sub MyTimer_Tick(sender As Object, e As EventArgs) Handles MyTimer.Tick
    		If Not MyBGW.IsBusy Then
    			MyBGW.RunWorkerAsync()
    		End If
    	End Sub
    	Private Sub MyBGW_DoWork(sender As Object, e As DoWorkEventArgs) Handles MyBGW.DoWork
    		MessageBox.Show("Hi there! Your 5 minutes is up")
    		' here, you would put the code to
    		' run every 5 minutes
    	End Sub
    End Class


    Regards Les, Livingston, Scotland

    Wednesday, September 2, 2020 4:22 PM
  • "What kind of accuracy are you looking for?  5 minutes ± ??????"

    LOL.  I just threw that out as an example.  Calm down.  The number I am refreshing does not change very often...maybe 0-5 times a day...sometimes 2 times a week.  Not sure I need to update it every nano second.  :)


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 4:37 PM
  • "What kind of accuracy are you looking for?  5 minutes ± ??????"

    LOL.  I just threw that out as an example.  Calm down.  The number I am refreshing does not change very often...maybe 0-5 times a day...sometimes 2 times a week.  Not sure I need to update it every nano second.  :)


    ISV using VB.net and SQL Server

    Calm down?  The reason I asked was a complexity issue. 

        Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
            Task.Run(Sub() Every())
        End Sub
    
        Private Sub Every()
            Dim _wait As TimeSpan = TimeSpan.FromMinutes(5.0#) '<<<<<<<<<<<<
            Dim waiter As New Threading.ManualResetEvent(False)
            Do
                waiter.WaitOne(_wait)
                'your code here
                '
                'e.g.
                'to intereact with the UI use BeginInvoke or Invoke
                Me.BeginInvoke(Sub()
                                   Label1.Text = DateTime.Now.TimeOfDay.ToString("hh\:mm\:ss\.fff")
                               End Sub)
            Loop
        End Sub
    


    Search Documentation

    SerialPort Info

    Multics - An OS ahead of its time.

     "Those who use Application.DoEvents have no idea what it does

        and those who know what it does never use it."    former MSDN User JohnWein

    Wednesday, September 2, 2020 4:45 PM
  • You code seems simple.  But this line is not valid because it seems to want arguments for Timer.

     Dim WithEvents MyTimer As New Timer

    Any ideas?


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 4:47 PM
  • You code seems simple.  But this line is not valid because it seems to want arguments for Timer.

     Dim WithEvents MyTimer As New Timer

    Any ideas?


    ISV using VB.net and SQL Server

    Hi

    Did you include the line

    Imports System.ComponentModel


    Regards Les, Livingston, Scotland

    Wednesday, September 2, 2020 4:49 PM
  • Les,  yes I did.

    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 4:57 PM
  • Les,  yes I did.

    ISV using VB.net and SQL Server

    Hi

    It works fine here, so I can't guess why not working your end. What is the exception you are getting?


    Regards Les, Livingston, Scotland

    Wednesday, September 2, 2020 5:01 PM
  • You code seems simple.  But this line is not valid because it seems to want arguments for Timer.

     Dim WithEvents MyTimer As New Timer

    Any ideas?


    ISV using VB.net and SQL Server

    It's looking at the Timer I recommended, do this

    Dim WithEvents MyTimer As New System.Windows.Forms.Timer


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, September 2, 2020 5:11 PM
  • This modification seems to eliminate the error.  5 stars for you.

    Dim WithEvents MyTimer As New System.Windows.Forms.Timer


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 9:02 PM
  • Below is the code used for my test.  It includes Karen's modification.

    Imports System.Data.SqlClient
    Imports System.Data.SqlTypes
    Imports System.Runtime.CompilerServices
    Imports System.Threading
    Imports Timer = System.Threading.Timer
    Imports System.ComponentModel
    Public Class MainTest
    
        'Dim WithEvents MyTimer As New Timer
        Dim WithEvents MyTimer As New System.Windows.Forms.Timer
        Dim WithEvents MyBGW As New BackgroundWorker
        Private Sub MainTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            With MyTimer
                .Interval = 1 * 60 * 1000
                .Enabled = True
            End With
        End Sub
        Private Sub MyTimer_Tick(sender As Object, e As EventArgs) Handles MyTimer.Tick
            If Not MyBGW.IsBusy Then
                MyBGW.RunWorkerAsync()
            End If
        End Sub
        Private Sub MyBGW_DoWork(sender As Object, e As DoWorkEventArgs) Handles MyBGW.DoWork
    
            ' here, you would put the code to
            ' run every 5 minutes
            Dim Connection1 As New SqlConnection(ConnectionString)
            Dim Command1 As New SqlCommand()
            Command1.Connection = Connection1
    
            ' Primary resource parent
            Command1.CommandText = "SELECT Count(account_no) FROM client " &
                                                "WHERE status = 'Active'"
    
    
            ' Open connection if closed
            If Connection1.State = ConnectionState.Closed Then Connection1.Open()
    
            ClientTotal.Text = Convert.ToInt32(Command1.ExecuteScalar)
    
    
            ' Close connection if open
            If Connection1.State = ConnectionState.Open Then Connection1.Close()
    
        End Sub
    
        Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
            Dispose()
        End Sub
    End Class
    

    When the timer triggers the code I want to run, the attached error pops up.

    Any ideas?


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 9:26 PM
  • Here is the error produced by "Dim WithEvents MyTimer As New Timer"


    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 9:29 PM
  • Hi

    The BackGroundWorker is running on a different thread and so, you don't have direct access to the main thread (where your Label/TextBox is).

    So, try changing your line to

    Invoke(Sub() ClientTotal.Text = Convert.ToInt32(Command1.ExecuteScalar)


    Regards Les, Livingston, Scotland


    • Edited by leshay Wednesday, September 2, 2020 9:33 PM
    • Marked as answer by Jeff07 Wednesday, September 2, 2020 9:44 PM
    Wednesday, September 2, 2020 9:33 PM
  • That worked...thank you so very much.  Next time I am in Scotland several beers are on me!

    ISV using VB.net and SQL Server

    Wednesday, September 2, 2020 9:47 PM
  • That worked...thank you so very much.  Next time I am in Scotland several beers are on me!

    ISV using VB.net and SQL Server

    Hi

    LOL - pity I'm a non-drinker 😊


    Regards Les, Livingston, Scotland

    Wednesday, September 2, 2020 9:48 PM