[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
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
Quote:
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
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.
Re: Threading.Timer updating UI
Or just use a System.Windows.Forms.Timer which automatically invokes your handlers on the main thread :)
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
Re: Threading.Timer updating UI
Quote:
Originally Posted by
Mutant_Fruit
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.
Re: Threading.Timer updating UI
Quote:
Originally Posted by
monalin
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.
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.