?
Solved

Running threads from a timer vb.net

Posted on 2006-05-26
11
Medium Priority
?
1,553 Views
Last Modified: 2008-02-26
Hello experts I have a thread the query's a database.  I want to run this thread every 5 minutes so I thought using a timer to run a thread would work, but I keep getting errors like:  Thread is already running.  I dont think I am properly closing out the thread before I try to restart it.  My code is below.  I start the thread in the form load event and I am trying to stop it in the findjobs procedure.  Any ideas?

Dim jstart As Thread = New System.Threading.Thread(AddressOf findjobs)

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lblloading.Visible = True
            jstart.Start()
        tjobs.Start() 'This timer used to increment label on form
         Timer2.Start() 'this timer runs the jstart thread every 5 minutes
    End Sub
   
 Sub findjobs()
        If jobstarted = False Then
            lblloading.Text = "Jobs Loading"
                   Cursor = Cursors.WaitCursor
       Buildjobs(i have a query that goes here) 'procedure contains a datareader to query the database
                Cursor = Cursors.Default
                  tjobs.Stop()
            If jstart.IsAlive Then 'Having problems here properly ending thread
                jstart.Suspend()
            End If
        End If
End Sub


 Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        'Timer2 event that updates the job list every 5 minutes if press is not running
        jstart.Resume() 'trying to run thread from timer
        tjobs.Start()
        '  findjobs()
    End Sub
0
Comment
Question by:tentavarious
  • 4
  • 4
  • 3
11 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16769762
I assume the work in the thread does not take five minutes to complete?  The thread will exit and stop by itself once the last line in the thread is executed.

So just create a new thread each time the Timer fires...

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        lblloading.Text = "Jobs Loading"
        Dim jstart As Thread = New System.Threading.Thread(AddressOf findjobs)
        jstart.Start()
    End Sub

Also, I don't understand why you are trying to stop the thread from within itself:

    Sub findjobs()
        Cursor = Cursors.WaitCursor
        Buildjobs(i have a query that goes here) 'procedure contains a datareader to query the database
        Cursor = Cursors.Default
        tjobs.Stop()
    End Sub
0
 

Author Comment

by:tentavarious
ID: 16769837
tjobs.stop is a timer that just increments  a label.  I was thinking the same thing creating a new thread everytime.  I wasnt sure if they terminate on their own, but you answered my question.  Also how come I cant start a timer from a thread?
0
 

Author Comment

by:tentavarious
ID: 16769887
The reason for stopping timer2, is sometimes the connection to the database will not work and it may take 5 minutes to establish a connection, so I want to make sure the timer2 tick event doesnt fire again until the buildjobs procedure has completed.

Something like this but how can i restart timer2 after the jstart thread is finished running?
   
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        'Timer2 event that updates the job list every 5 minutes if press is not running
        If jobstarted = False Then
            Timer2.Stop() 'Stop timer and wait for jstart thread to complete
            lblloading.Visible = True
            Dim jstart As New Thread(AddressOf findjobs)
            jstart.Start()
            tjobs.Start()
        End If
    End Sub
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 1000 total points
ID: 16769911
You're really not supposed to interact with GUI components from a thread.

The robust way to handle these things is to encapsulate the thread in a class and make the class raise events to notify the main UI of status changes, etc.  The main UI should then use Delegates and the Invoke() method to marshal the call from the thread back onto the main UI thread where it is safe to update/interact with GUI components.

Study the model here:
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21729609.html
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16769928
Study the example.  =)

What you can do is turn off the Timer once it fires.  Start the thread in the class and then wait for a "complete" event to be fired.  When the main UI receives it (and you've correctly marshalled the call back onto the main UI) then you can simply turn the timer back on.

So instead of creating a new thread each time you would instead create a new instance of the class (which encapsulates the thread) each time.
0
 
LVL 5

Expert Comment

by:mydasx
ID: 16771044
listen to idlemind.  Goto an event driven model, instead of time and pray.  Time and pray is REALLY dangerous, where as an asycronous approach will be safe 100 percent of the time.
0
 

Author Comment

by:tentavarious
ID: 16771515
I dont have that great, of a grasp, on delegates and how to handle them.  Could someone give a quick example using my code above.  For now, until I can get it to work correctly; I just took the thread out.  A small example would be great though.  My main problem is that within the buildjobs and findjobs procedure, I do a lot of control handling within the form that they are located on.  For example I have 2 listboxes that contain the items from the query and a number of checkboxes and buttons that get changed depending on the results of the query. It would get very complicated accessing all those controls from the new thread class I would have to create, but if thats what I have to do I mind as well start now.
0
 
LVL 5

Expert Comment

by:mydasx
ID: 16771770
actually, if your make your thread class evented... your form will handle all the updating of the controls same as it is now.  Your form will subscribe to the events found in the thread.
0
 
LVL 5

Expert Comment

by:mydasx
ID: 16771857
Ok crash course:

you need to do 5 things to create a custom event.

1.  Create an args class that you will pass data from the method that throws the event to the method that handles the event with

2.  Create a delegate which is a function pointer for your event, (i.e., a pointer to the methods that handle your event)

3.  Create a public event in the class that will raise the event using the delegate as its type

4.  Raise the event as needed in the class

5.  Subscribe to the event from some other class.
0
 

Author Comment

by:tentavarious
ID: 16771858
I did something a little unorthodox, can you see any problems in my code below?  Form1 is my main class and I am just accessing it from my thread class.  I make a new instance of the thread class in my timer, but I cant get my label to update when the thread class fires.
 
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        'Timer2 event that updates the job list every 5 minutes if press is not running
        If jobstarted = False Then
            Timer2.Stop()
                    Dim d As New Buildjobsclass
            Timer2.Start()
        End If
    End Sub

Public Class Buildjobsclass
    Public Sub New()
        Dim j As System.Threading.Thread
        Dim d As New Form1
        j = New System.Threading.Thread(AddressOf d.findjobs)
        j.Start()
        d.tjobs.Start()
    End Sub
End Class
0
 
LVL 5

Expert Comment

by:mydasx
ID: 16771962
Ok an example:  here is how i raise a custom event from one of my threads to pass a message to a listbox

1.  Args (this sits in its own .vb file and i give its own namespace)
Public Class StatusMessageEventArgs
        Private mstrMessage As String
        Public Sub New(ByVal message As String)
            Me.mstrMessage = message
        End Sub
        Public Property Message() As String
            Get
                Return Me.mstrMessage
            End Get
            Set(ByVal value As String)
                Me.mstrMessage = value
            End Set
        End Property
    End Class

2.  delegate (this sits in the same .vb as the class that raises events.  It sits outside the class, the class imports the args namespace)
Public Delegate Sub StatusMessageEventHandler(ByVal e As StatusMessageEventArgs)

3.  event (inside the class create the event using the event keyword)
Public Event NewStatusMessage As StatusMessageEventHandler

4.  Raise the event as needed inside the threaded class(i use a method to do this, because in more robust events, you need to do some
work on the data before you put it in the args, in this case thats not really necessary but a good habit)

Public Sub RaiseNewStatusMessage(ByVal message As String)
            RaiseEvent NewStatusMessage(New StatusMessageEventArgs(message))
End Sub

5.  Subscribe to the event (do this in your form either form_load if you want it global, or on the fly if you want it dynamic don't get thrown off by Me.ThreadController, the threadcontroller is the list of threads wrapped in classes (which is what was suggested you do for your threads above))
AddHandler Me.TheadController.NewStatusMessage, AddressOf StatusMessageRecieved
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question