CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Sep 2004
    Posts
    65

    Forms Timer and Thread problem

    Hi,

    I have an application which contains a form with a Forms.Timer. For some reason, the tick event is not getting called... Somehow this is connected to the fact that I start a new thread...

    Here are some code snippets.
    Code:
     Private Sub tmrSchedule_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrSchedule.Tick
    
            Dim processor As New EDIProcessor
    
    
            AddHandler processor.ProcessingComplete, AddressOf EDIProcessor_ProcessingComplete
    
    
            If tmrSchedule.Enabled Then tmrSchedule.Stop()
            ediWorker = New Thread(AddressOf processor.Run)
            ediWorker.Start()
            last = 0
    
            'Call Me.EDIProcessor_ProcessingComplete("")
        End Sub
    
    
        Public Sub EDIProcessor_ProcessingComplete(ByVal msg As String)
            'Do we need to somehow remove handlers here?
            lstInfo.Items.Add("Process Complete " & msg)
                Call scroll()
                tmrSchedule.Enabled = True
                tmrSchedule.Start()
                pnlTransaction.Text = ""
        End Sub
    I disable the timer in the timer tick and enable it again when the processing is complete. I don't understand it, but the timer never fires after that, even though tmrSchedule.Enabled = true, and the interval is set to 20000, so it should be called again 20 seconds after the thread calls the Processing_Complete Event. Processing_Complete event is fired, and everything executes, but tmrSchedule.Tick is never fired again.

    tmrSchedule is a Forms timer and not a threading timer. Also, I commented out the creation and starting of the thread, and the timer worked... I do not reference the timer in any other code in the application...

    Any clues on why this would happen?

    Thanks,
    Ranthalion

  2. #2
    Join Date
    Jan 2003
    Location
    7,107 Islands
    Posts
    2,487

    Re: Forms Timer and Thread problem

    you have to use the form invoke method to start the timer from EDIProcessor_ProcessingComplete sub.

    ex.

    me.invoke(new methodinvoker(addressof tmrSchedule.Start()))
    Busy

  3. #3
    Join Date
    Sep 2004
    Posts
    65

    Re: Forms Timer and Thread problem

    Thanks! That works. I don't understand why it is different from what I had, or why invoke is needed instead of just enabling, or starting, the timer by itself. Do you know of any sites where I can get more information on this kind of problem?

    (The Processing_Complete Event is thrown from a different thread, but it is caught by the forms thread isn't it? So this isn't a case of a cross thread issue, is it?)

    Thanks,
    Ranthalion

  4. #4
    Join Date
    Jun 2001
    Location
    MO, USA
    Posts
    2,868

    Re: Forms Timer and Thread problem

    >The Processing_Complete Event is thrown from a different thread, but it is caught by the forms thread isn't it?

    Nope, the event handler runs on the same thread as it was thrown. You can prove this to yourself by giving the thread a name and checking the current threads name in the event handler.

  5. #5
    Join Date
    Sep 2004
    Posts
    65

    Re: Forms Timer and Thread problem

    Ok, so now that I understand this a little better, I have rewritten some of the code. The problem is that it just seems wrong, like I'm missing something obvious...

    Here's what I have now...
    Code:
    Private Sub EDIScheduler_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Thread.CurrentThread.Name = "GUI"
        End Sub
    
        Private Sub tmrSchedule_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrSchedule.Tick
    
            Dim processor As New EDIProcessor
    
            AddHandler processor.RunningJob, AddressOf EDIProcessor_RunningJob
            AddHandler processor.ProcessingComplete, AddressOf EDIProcessor_ProcessingComplete
    
            If tmrSchedule.Enabled Then tmrSchedule.Stop()
            ediWorker = New Thread(AddressOf processor.Run)
            ediWorker.Name = "ediWorker"
            ediWorker.Start()
            last = 0
    
        End Sub
    
        Public Sub EDIProcessor_ProcessingComplete(ByVal msg As String)
    
            If (ediWorker.Name = Thread.CurrentThread.Name) Then
                Me.Invoke(New EventDelegate(AddressOf EDIProcessor_ProcessingComplete), New Object() {msg})
            Else
                'Do we need to somehow remove handlers here?
                lstInfo.Items.Add("Process Complete " & msg)
                Call scroll()
                Me.Invoke(New MethodInvoker(AddressOf tmrSchedule.Start))
                'tmrSchedule.Enabled = True
                'tmrSchedule.Start()
                pnlTransaction.Text = ""
            End If
        End Sub
    So, basically, I'm naming my GUI thread (because otherwise it didn't have a name...) and my worker thread. Then, in the event handler, I'm checking the names, and invoking the handler again if I'm not on the GUI thread... Is this the wrong way to do it?

    On a side note: I hook up multiple event handlers in the timer tick event. Should I remove those handlers in the ProcessingComplete event, or is that unnecessary? (or would it cause problems...)

    [Edit: Ok, so I found InvokeRequired, and I can use that, but it doesn't really change the situation of having to check it on every event handler....]

    Thanks,
    Ranthalion
    Last edited by Ranthalion; May 16th, 2007 at 03:07 PM. Reason: New Info

  6. #6
    Join Date
    Jan 2003
    Location
    7,107 Islands
    Posts
    2,487

    Re: Forms Timer and Thread problem

    as we know since the object was hosted onto a separate thread all of its events also will run on that thread. the remarks in the InvokeRequired at msdn explains why you have to call the timer control this way.. there is no need to check the thread name and there is no need to remove the handlers in the EDIProcessor_ProcessingComplete sub as the object was instantiated per timer event, it will be disposed off automatically.

    Code:
    Public Sub EDIProcessor_ProcessingComplete(ByVal msg As String)
    
    '        If (ediWorker.Name = Thread.CurrentThread.Name) Then
    '            Me.Invoke(New EventDelegate(AddressOf EDIProcessor_ProcessingComplete), New Object() {msg})
    '        Else
                'Do we need to somehow remove handlers here?
                lstInfo.Items.Add("Process Complete " & msg)
                Call scroll()
                Me.Invoke(New MethodInvoker(AddressOf tmrSchedule.Start))
                'tmrSchedule.Enabled = True
                'tmrSchedule.Start()
                pnlTransaction.Text = ""
    '        End If
        End Sub
    Busy

  7. #7
    Join Date
    Jun 2001
    Location
    MO, USA
    Posts
    2,868

    Re: Forms Timer and Thread problem

    >there is no need to check the thread name

    Correct. My suggestion about naming the threads was simply for debugging purposes so you can see what's going on. InvokeRequired is how you should check in code during runtime.

  8. #8
    Join Date
    Sep 2004
    Posts
    65

    Re: Forms Timer and Thread problem

    Thanks DSJ and Thread1! That set me off on my journey to learn more about threading... It seems like I should have designed the EDIProcessor class to work a little differently and handle the multithreading itself, instead of the way I did it... I'm off to the bookstore today to look for a book on mulithreaded programming then.

    Thanks again!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured