tags:

views:

836

answers:

4

Original post: http://stackoverflow.com/questions/725413/how-to-access-a-timer-from-another-class-in-c

I tried everything.

-Event

-Invoke can't be done,because Timers don't have InvokeRequired property.

-Public/internal property

Nothing worked,the code is being executed,the timer.Enabled property is being set to "true" ,but it doesn't Tick.If I call the event or just change the property from the form class in a NON-static method - it does tick and works.

I never knew it would take me a day and probably more to acquire how to use a decent timer.

If there's no way to do this,is there anything else I can use that works similiar to the timer(delay,enable/disable)?

+4  A: 

You should use the Timer class from the System.Timers namespace, and not the WinForms Timer control, if you want multi-threading support. Check the MSDN documentation for the WinForms Timer control for more information:

http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

David M
+1 for beating me to it :-)
Jakob Christensen
Was suprised to be first to this one...
David M
While this will get the Elapsed event to fire (the System.Timer.Timer has an Elapsed event as opposed to the System.Windows.Forms.Timer's Tick event), it will be firing within the context of the calling thread and, depending upon what you do in the event, could result in a System.InvalidOperationException such as, "Cross-thread operation not valid: Control 'X' accessed from a thread other than the thread it was created on."
raven
+1  A: 

I accidently tried to use invoke again,this time it worked,but I'll accept your answer,DavidM.

    public bool TimerEnable
    {
        set
        {
            this.Invoke((MethodInvoker)delegate
            {
                this.timer.Enabled = value;
            });
        }
    }


    public static void timerEnable()
    {
        var form = Form.ActiveForm as Form1;
        if (form != null)
            form.TimerEnable = true;
    }
John
+1  A: 

Just because System.Windows.Forms.Timer doesn't have the ability to invoke, doesn't mean that your form doesn't. Try my InvokeEx from the second (or other) thread to enable the timer.

public static class ControlExtensions
{
  public static TResult InvokeEx<TControl, TResult>(this TControl control,
                            Func<TControl, TResult> func)
    where TControl : Control
  {
    if (control.InvokeRequired)
    {
      return (TResult)control.Invoke(func, control);
    }
    else
    {
      return func(control);
    }
  }
}

With this, the following code worked for me:

new Thread(() =>
  {
    Thread.Sleep(1000);
    this.InvokeEx(f => f.timer1.Enabled = true);
  }).Start();

And the timer instantly sprung to life after the 1 second.

Samuel
+3  A: 

You don't need to check InvokeRequired on the Control iteself, you can check the property on the class e.g.:

if (this.InvokeRequired) 
{ 
    BeginInvoke(new MyDelegate(delegate()
    {
        timer.Enabled = true;
    }));
}
Terrapin