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

    [RESOLVED] Threading.Timer updating UI

    Hi,

    I am using a System.Threading.Timer and I'm trying to update a form's UI each time the timer fires. When I push a button I start the timer, execute some task that takes a while to complete and then stop the timer.

    I have the following code:
    Code:
    DateTime dtStart;
    private System.Threading.Timer tmr;
    
    private void Form1_Load(object sender, EventArgs e)
    {
         tmr = new System.Threading.Timer(new TimerCallback(timer_Elapsed), null, System.Threading.Timeout.Infinite, 1000);
    }
    
    private void btnWebSync2_Click(object sender, EventArgs e)
    {
          dtStart = DateTime.Now;
          tmr.Change(0, 1000);                                             // start the timer
          Thread.Sleep(5000);                                              // some long running task
          tmr.Change(System.Threading.Timeout.Infinite, 1000); // stop the timer
    }
    
    void timer_Elapsed(object state)
    {
          TimeSpan ts = DateTime.Now.Subtract(dtStart);
          string elapsedTime = string.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
          Debug.Print(elapsedTime);
    
          this.Invoke((MethodInvoker)delegate()
          {
               label1.Text = "Elapsed time - " + elapsedTime;
          });
    }
    I have calls to Debug.Print in the timer callback and I can see that the timer is actually firing but my UI is only updated when the timer is stopped. Any ideas what I'm doing wrong?

    Thanks,

    dlarkin77

  2. #2
    Join Date
    Jul 2006
    Posts
    297

    Re: Threading.Timer updating UI

    Because you're calling Thread.Sleep(5000) in the UI thread. So that thread is blocked until you're done. Also note

    System.Threading.Timer is a simple, lightweight timer that uses callback methods and is served by thread pool threads. It is not recommended for use with Windows Forms, because its callbacks do not occur on the user interface thread. System.Windows.Forms.Timer is a better choice for use with Windows Forms. For server-based timer functionality, you might consider using System.Timers.Timer, which raises events and has additional features.
    From the following article
    http://msdn.microsoft.com/en-us/libr...ing.timer.aspx

  3. #3
    Join Date
    Jul 2007
    Location
    Illinois
    Posts
    517

    Re: Threading.Timer updating UI

    It sounds like something is blocking the user interface thread. Take a look at the call to Thread.Sleep(5000); That's on the user interface thread and its putting it to sleep.

    I would suggest that you run that code on a separate thread and when the call ends, stop the timer.

    Code:
            private DateTime startTime;
            private System.Timers.Timer progressTimer = new System.Timers.Timer(1000);
            private Thread workerThread;
    
            public ExamplePrintForm()
            {
                InitializeComponent();
    
                this.progressTimer.Elapsed += progressTimer_Elapsed;
                this.progressTimer.SynchronizingObject = this;
                this.workerThread = new Thread(PerformSomeWork);
            }
    
            private void startButton_Click(object sender, EventArgs e)
            {
                this.startTime = DateTime.Now;
                this.progressTimer.Start();
                this.workerThread.Start();
            }
    
            private void progressTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                TimeSpan timeWorking = DateTime.Now.Subtract(this.startTime);
    
                this.timeElapsedLabel.Text = timeWorking.ToString();
            }
    
            private void PerformSomeWork()
            {
                // Just some arbitrary working here :)
                Thread.Sleep(5000);
                this.progressTimer.Stop();
            }
    It needs a bit of work but its the basic jist. I also used a System.Timers.Timer to perform the updated since it is simpler to use and allows you to specify a SyncronizingObject so you dont have to manually Invoke your controls to avoid a CrossThreadException.
    R.I.P. 3.5" Floppy Drives
    "I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein

  4. #4
    Join Date
    May 2007
    Posts
    1,546

    Re: Threading.Timer updating UI

    Or just use a System.Windows.Forms.Timer which automatically invokes your handlers on the main thread
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  5. #5
    Join Date
    Oct 2004
    Posts
    206

    Re: Threading.Timer updating UI

    Hi,

    I've changed my code so that it is more like RaleTheBlade's and it's now working fine.

    Thanks very much,

    dlarkin77

  6. #6
    Join Date
    Jul 2006
    Posts
    297

    Re: Threading.Timer updating UI

    Quote Originally Posted by Mutant_Fruit View Post
    Or just use a System.Windows.Forms.Timer which automatically invokes your handlers on the main thread
    This is my recomendation as well. As it is recommended by the documentation and will result in cleaner code.

  7. #7
    Join Date
    Jul 2007
    Location
    Illinois
    Posts
    517

    Re: Threading.Timer updating UI

    Quote Originally Posted by monalin View Post
    This is my recomendation as well. As it is recommended by the documentation and will result in cleaner code.
    Thats if you dont mind a timer being slightly off some times. The System.Windows.Forms timer works pretty good but if you have a time critical application then the System.Timers.Timer or System.Threading.Timer is a better choice.
    R.I.P. 3.5" Floppy Drives
    "I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein

  8. #8
    Join Date
    May 2007
    Posts
    1,546

    Re: [RESOLVED] Threading.Timer updating UI

    The System.Windows.Forms timer is 'inaccurate' because it executes its callback on the main thread. So if the mainloop is busy, the timer will be delayed.

    The original poster wants to use a timer to update his gui, so that means he must execute the callback on the main thread which means no matter how accurate his timer is, he'll still have exactly the same inaccuract as teh S.W.F.Timer.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

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