Can't Start .NET Windows Forms Timer From Second Thread

A

Axel Dahmen

Hi,

I've written a small tool using two threads:

a) GUI thread
b) Worker thread

The worker thread doesn't seem to be able to start the first thread's timer object. Can somebody please enlighten me why this happens?

This is what I did:

Created a form, added a Timer control, added a timer event handler to the form.

Within InitializeComponent() I set...

this.timer1 = new System.Windows.Forms.Timer(this.components);
this.timer1.Interval = 100;
this.timer1.Tick = new System.EventHandler(this.timer1_Tick);
this.timer1.Enabled = false;

When the second thread finishes, it enables the timer to update some flags and to start an animation:

private void FinishedWork()
{
this.timer1.Enabled = true;
}


private void timer1_Tick(object sender, System.EventArgs e)
{
...

Invalidate();
}

But this doesn't start the timer! timer1_Tick() is never called!

If I enable the timer from within the first thread, everything works fine.

Why can't I start the timer from within the second thread? Is there an alternative approach for re-activating the first thread after the work has been done? In the end I will have x worker processes, each supposed to reactivate the timer of a control they are associated with. (Each control will start its own worker process and show the result when finished.)

TIA,
Axel Dahmen
 
T

Tim Mackey

hi
you might be doing invalid cross thread operations. if you debug the client
from within VS you should get an exception raised about this that wouldn't
occur if running from outside VS.
you can check if it is valid to call Invalidate() from the timer_tick event
by first checking if the Form.InvokeRequired property is true. if it is
true, then you need to transfer execution of the function to the UI thread,
like so;

delegate void timer1_TickDelegate(object sender, System.EventArgs e);
private void timer1_Tick(object sender, System.EventArgs e)
{
if(this.InvokeRequired)
{
BeginInvoke(new timer1_TickDelegate(this.timer1_Tick), new
object[]{sender, e});
return;
}

Invalidate();
}

hope this helps
tim



Hi,

I've written a small tool using two threads:

a) GUI thread
b) Worker thread

The worker thread doesn't seem to be able to start the first thread's timer
object. Can somebody please enlighten me why this happens?

This is what I did:

Created a form, added a Timer control, added a timer event handler to the
form.

Within InitializeComponent() I set...

this.timer1 = new System.Windows.Forms.Timer(this.components);
this.timer1.Interval = 100;
this.timer1.Tick = new System.EventHandler(this.timer1_Tick);
this.timer1.Enabled = false;

When the second thread finishes, it enables the timer to update some flags
and to start an animation:

private void FinishedWork()
{
this.timer1.Enabled = true;
}


private void timer1_Tick(object sender, System.EventArgs e)
{
...

Invalidate();
}

But this doesn't start the timer! timer1_Tick() is never called!

If I enable the timer from within the first thread, everything works fine.

Why can't I start the timer from within the second thread? Is there an
alternative approach for re-activating the first thread after the work has
been done? In the end I will have x worker processes, each supposed to
reactivate the timer of a control they are associated with. (Each control
will start its own worker process and show the result when finished.)

TIA,
Axel Dahmen
 
L

Linda Liu[MSFT]

Hi Axel,

I performed a test based on your description and did reproduce the problem
on my side.

IMO, in your scenario, the Tick event of the System.Windows.Forms.Timer
component is not raised at all after you set the Enable property of the
Timer to true in a second thread. This may be a cross-thread operation
issue in WinForm applications. It's strongly recommended that WinForm
controls/components are accessed in the thread that creates them.

To workaround this problem, call the Control.Invoke method to execute a
delegate on the UI thread to start the Timer component.

The following is a sample:

private void FinishedWork()
{
StartTimer();
}
delegate void StartTimerDelegate();
public void StartTimer()
{
if (this.InvokeRequired)
{
this.Invoke(new StartTimerDelegate(StartTimer));
}
else
{
this.timer1.Start();
}
}

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Axel Dahmen

Tim and Linda,

works perfect now after applying your suggestions. Thanks a lot for helping me out!

Best regards,
Axel Dahmen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top