-
September 2nd, 2009, 10:31 AM
#1
[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
-
September 2nd, 2009, 10:39 AM
#2
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
-
September 2nd, 2009, 10:47 AM
#3
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
-
September 2nd, 2009, 11:17 AM
#4
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.
-
September 2nd, 2009, 11:18 AM
#5
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
-
September 2nd, 2009, 12:56 PM
#6
Re: Threading.Timer updating UI
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.
-
September 2nd, 2009, 05:46 PM
#7
Re: Threading.Timer updating UI
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.
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
-
September 2nd, 2009, 05:56 PM
#8
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|