Results 1 to 13 of 13

Thread: [RESOLVED] Threading.Timer and Thread.Sleep - unexpected interaction

  1. #1

    Thread Starter
    Lively Member
    Join Date
    May 2002
    Posts
    103

    Resolved [RESOLVED] Threading.Timer and Thread.Sleep - unexpected interaction

    All,

    Following is a simplified snippet from a program I am currently developing:

    Imports System.Threading
    Code:
    Public Class myClass
        Dim bIsRunning As Boolean = False
    
        Dim myTimer As Threading.Timer
    
        Private Sub btn_Click(sender As System.Object, e As System.EventArgs) Handles btn.Click
            If Not bIsRunning Then 
                bIsRunning = True
                myTimer = New Threading.Timer(AddressOf myTimer_Tick, Nothing, 0, Timeout.Infinite)
            Else 
                bIsRunning = False
                Thread.Sleep(3000)
                myTimer.Dispose()
                myTimer = Nothing
            End If
        End Sub
    
        Private Sub myTimer_Tick(ByVal state As Object)
            <do stuff, including updating the form on which btn resides>
    
            If bIsRunning Then
                waitTime = <calculate value>
                myTimer.Change(waitTime, Timeout.Infinite)
            End If
        End Sub
    End Class
    While this approach is not ideal (none of my attempts with various locking mechanisms worked well), this does get the job done. But. For some reason that i do not understand, the Thread.Sleep() call in Btn_Click causes myTimer_Tick to sleep as well. I have verified this by inserting Console.Write statements into myTimer_Tick.

    I was under the impression that the Threading.Timer ran in its own thread, thus a Thread.Sleep in the parent thread should not affect it. Obviously, my impression is wrong. Can you please a) point me to something that explains this behavior and b) suggest an approach that obviates this problem.

    Thank you.

  2. #2
    Fanatic Member
    Join Date
    Oct 2011
    Location
    Sydney, Australia
    Posts
    756

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    Hi,
    I couldnt be certain but I think you need to create a new thread to run the timer on otherwise it runs on the UI thread. Make a new thread and in that create your timer, see what happens.
    My CodeBank Submissions
    • Listbox with transparency and picture support - Click Here
    • Check for a true internet connection - Click Here
    • Open Cash drawer connected to receipt printer - Click Here
    • Custom color and size border around form - Click Here
    • Upload file to website without user logins, includes PHP - Click Here
    • List All Removable USB Storage Devices - Click Here
    • Custom On/Off Slide Control - Click Here
    • Insert multiple rows of data into one database table using parameters - Click Here
    • Trigger USB/Serial Cash Drawer - Click Here

  3. #3
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    Actually, to be honest, I think the timer DOES run on a secondary thread... the blocking comes from the Tick event which is handled on the main UI Thread, which is currently sleeping due to the Thread.Sleep command.

    Think of the thread.sleep as Developer.Sleeping ... even though the AlarmClock_AlarmSounds event happens, because the Developer.Sleeping is in effect, the event is ignored.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4

    Thread Starter
    Lively Member
    Join Date
    May 2002
    Posts
    103

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    bensonsearch,

    Thank you for the reply. Your suggestion seemed like a good one - in fact, my code originally had a thread (but I got rid of it because I thought the timer ran in its own thread). However, since you suggested this, I put it back into my code - which now looks like the following:
    Code:
    Public Class myClass
        Dim bIsRunning As Boolean = False
    
        Dim trd As Thread
        Dim myTimer As Threading.Timer
    
        Private Sub btn_Click(sender As System.Object, e As System.EventArgs) Handles btn.Click
            If Not bIsRunning Then 
                bIsRunning = True
                trd = New Thread(AddressOf trdThread)
                trd.Start()
            Else 
                bIsRunning = False  **
                Thread.Sleep(3000)
                myTimer.Dispose()
                myTimer = Nothing
                trd.Abort()
                trd = Nothing
            End If
        End Sub
    
        Sub trdThread()
            myTimer = New Threading.Timer(AddressOf myTimer_Tick, Nothing, 0, Timeout.Infinite)
        End Sub
        
        Private Sub myTimer_Tick(ByVal state As Object)
            <do stuff, including updating the form on which btn resides>
    
            If bIsRunning Then
                waitTime = <calculate value> **
                myTimer.Change(waitTime, Timeout.Infinite)
            End If
        End Sub
    End Class
    Sadly, the issue remains - the Thread.Sleep call in btn_Click causes myTimer_Tick to sleep as well. (This has been confirmed with Console.Write statements at each of the two locations marked **. If the Thread.Sleep had no impact on myTimer_Tick, there should be no delay between the two Console.Write statements. However, the delay is equal to the Thread.Sleep time, thus the Thread.Sleep call in btn_Click causes myTimer_Tick to sleep.)

    This is getting very frustrating as this should be easy and I don't know what I am doing wrong.
    Last edited by groston; Dec 30th, 2014 at 12:29 AM.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    May 2002
    Posts
    103

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    techgnome,

    Thank you.

    Assuming you are correct, this seems like odd behavior. Why would the Tick event be handled in the UI thread? If you look at my second post (which was being written at the same time as your post), the Tick event seems to be handled by the UI thread even when the timer is launched from a secondary thread.

    How can I get the Tick handler out of the UI thread?

  6. #6
    Frenzied Member
    Join Date
    Jul 2011
    Location
    UK
    Posts
    1,335

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    The code in your Sub myTimer_Tick will be running on a different thread from the code in Sub btn_Click.

    I think you are using the timer in a somewhat unusual manner, and this is why you are having problems.

    This line:
    Code:
    myTimer = New Threading.Timer(AddressOf myTimer_Tick, Nothing, 0, Timeout.Infinite)
    is creating a Threading.Timer with a "due time" of 0 milliseconds, and a "period" of Timeout.Infinite.
    This means the callback delegate will be invoked just the once, immediately ("due time" = 0) but then never invoked again ("period" = Timeout.Infinite).

    However, the callback code has this line:
    Code:
    myTimer.Change(waitTime, Timeout.Infinite)
    where you reset the "due time" but leave the "period" unchanged.
    This means the callback delegate will be invoked again, just the once, after waitTime milliseconds ("due time" = waitTime), but then never invoked again ("period" = Timeout.Infinite).

    Of course, when it is actually invoked after waitTime milliseconds, the myTimer.Change line of code is executed again, the "due time" is set again, and the callback will be invoked again, just the once, after waitTime milliseconds. And on we go....

    So your timer is acting like a Timer, but it's your code that is causing it to tick after you manually reset the "due time". It's not repeatedly ticking automatically.

    So why's it failing immediately after you set your UI thread to sleep for 3 seconds? Well, at the same time you set Thread.Sleep(3000), you also set bIsRunning = False, and this global boolean acts in your callback sub (Sub myTimer_Tick) to stop the resetting of the "due time". So when blIsRunning is False, the callback code is not invoked anymore.

    If you want the timer to keep "ticking" while the UI thread sleeps, try moving bIsRunning = False to the last line of the Else... End If block.

    That said, given that you say you are updating the UI in the timer callback, I don't understand why you want to keep the timer running while the UI thread sleeps.

  7. #7
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    That said, given that you say you are updating the UI in the timer callback, I don't understand why you want to keep the timer running while the UI thread sleeps.
    Not only that, if he really is running his timers in secondary threads, he'll get (appropriately) cross-thread exception calls (or at least should) - unless they are appropriately invoked (which we don't know since that part was taken out).
    So there may be bigger issues.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #8

    Thread Starter
    Lively Member
    Join Date
    May 2002
    Posts
    103

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    All,

    Thanks for the replies.

    With regard to the manner in which I am calling timer: The Tick routine can take a large amount of time as compared to the period. I just did an experiment comparing the method shown here (adjusting due time) versus simply setting the value for the period. It turns our that the approach used here is far more accurate (in terms of maintaining the specified time between ticks). Thus, while seemingly odd looking, this actually works well. The author of this post, http://stackoverflow.com/questions/1...mer-in-c-sharp, seems to advocate a similar approach.

    With regard to the comment about moving the bIsRunning line: That will not work. The thing to remember is that the Tick event can get queued for execution, and if one disposes the timer (which, under this scenario would happen before the Tick is told to stop ticking) while a Tick is queued for execution, an error is thrown. (My apologies if the explanation is not spot on, but I have seen this error more than once while working on this.)

    With regard to cross-thread calls: The real code does use delegates/invoke and this has not been a problem.

    What I seem to have 'discovered' is that when Tick handler is in a separate class, it does seem to execute in a different thread from the UI.
    Last edited by groston; Dec 30th, 2014 at 07:09 PM.

  9. #9
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    Quote Originally Posted by groston View Post
    All,


    I was under the impression that the Threading.Timer ran in its own thread, thus a Thread.Sleep in the parent thread should not affect it. Obviously, my impression is wrong. Can you please a) point me to something that explains this behavior and b) suggest an approach that obviates this problem.

    Thank you.
    But you are not wrong...

  10. #10
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    I would expect that the timer tick code can be blocked if the UI thread has executed the sleep. Lets say that right before the tick is going to happen the button is pressed. It puts the UI to sleep for three seconds. Then the tick occurs and tries to update the UI but it can't because the UI is sleeping, so it has to wait. Eventually the sleep expires and then you dispose of the timer which may or may not affect the currently active tick.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  11. #11

    Thread Starter
    Lively Member
    Join Date
    May 2002
    Posts
    103

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    dbasnett,

    Thank you! I think you figured out the problem. It is not the Sleep in the UI Thread, per se, that is the problem, but rather the call to update the UI from the timer thread that is the problem. This 'second order' interaction had not occurred to me.

    FYI: My comment about having code in two classes was completely wrong - sorry.

  12. #12
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    Your problem is you use sleep. Why do you waste our time with comments like you handle UI invoking yet not show it.

    What I seem to have 'discovered' is that when Tick handler is in a separate class, it does seem to execute in a different thread from the UI.

    Are you serious? the threading.timers class raises it's tick event regardless on a seperate thread thats not the ui :/

  13. #13
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: Threading.Timer and Thread.Sleep - unexpected interaction

    Take a deep breath and ask for help with a full explanation. You don’t really know what you are saying.

Tags for this Thread

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