2

I'd like to change a timer interval in another thread:

    class Context : ApplicationContext {
       private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
       public Context() {
           timer.Interval = 1;
           timer.Tick += timer_Tick;
           timer.Start();
           Thread t = new Thread(ChangeTimerTest);
           t.Start();
       }
       private void ChangeTimerTest() {
           System.Diagnostics.Debug.WriteLine("thread run");
           timer.Interval = 2;
       }
       private void timer_Tick(object sender,EventArgs args) {
           System.Diagnostics.Debug.WriteLine(System.DateTime.Now.ToLongTimeString());
       }
    }

But the timer stops when I change the interval in the new thread. No errors, timer just stops. Why is this happening and how can I fix it?

thx

frau_muller
  • 23
  • 1
  • 5

2 Answers2

1

Try this, I tried it and it works, I only changed new interval from 2 to 2000ms so you can see the difference in the Output. You have to change interval in a thread safe manner your interval because the timer is in UI thread context. In these cases it is recommended to use delegates.

private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    public void Context() {
        timer.Interval = 1;
        timer.Tick += timer_Tick;
        timer.Start();
        Thread t = new Thread(ChangeTimerTest);
        t.Start();
    }
    delegate void intervalChanger();
    void ChangeInterval()
    {
        timer.Interval = 2000;
    }
    void IntervalChange()
    {
        this.Invoke(new intervalChanger(ChangeInterval));
    }
    private void ChangeTimerTest() {
        System.Diagnostics.Debug.WriteLine("thread run");
        IntervalChange();
    }
    private void timer_Tick(object sender,EventArgs args) {
        System.Diagnostics.Debug.WriteLine(System.DateTime.Now.ToLongTimeString());
    }
Nikola Davidovic
  • 8,556
  • 1
  • 27
  • 33
  • yes . this work :) . but my class not contain method "invoke":( . class MainContext : ApplicationContext . How i can added this method ? – frau_muller Oct 10 '12 at 20:44
  • Well, you should find out how to pass your Form reference to your class, maybe trough constructor arguments. Than you should call myFormReference.Invoke I can't give you a complete answer because I don't know how you are using Context class, but it is evidently that timer is executing in you UI thread, hence you should change it in a thread-safe manner – Nikola Davidovic Oct 10 '12 at 20:50
  • There is a workaround how to get your form wherever you want in your code but I am not suggesting that you should use it. When I used it, it was very convenient but I'm not sure if it's totally OK. static class Program { public static Form myForm; [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); myForm = new Form1(); Application.Run(myForm); } } – Nikola Davidovic Oct 10 '12 at 20:55
  • the fact is that I do not want to create a form. I create only tray. of the tray, I open the console (in new thread). timer operates independently of the console. and from the console, I want to change the interval timer. – frau_muller Oct 10 '12 at 21:09
  • Any control has Invoke() method that you can use. Have you tried to execute your previous code in only a ConsoleApplication? – Nikola Davidovic Oct 10 '12 at 21:18
  • the parent of mainContext is ApplicationContext . ApplicationContext not contain invoke(); static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainContext()); } } – frau_muller Oct 10 '12 at 21:38
  • Thx for link http://stackoverflow.com/questions/7011886/invoking-delegate-in-a-console-application That's it! thx you very match . good night :) – frau_muller Oct 10 '12 at 22:04
  • Check my last answer, I think it will help you. – Nikola Davidovic Oct 10 '12 at 22:05
0

In addition to my previous answer, since you are not using Forms, try to change your System.Windows.Forms.Timer to System.Timers.Timer. Note that it has Elapsed Event, not Tick. The following is the code:

System.Timers.Timer timer = new System.Timers.Timer();
    public Context() {
        timer.Interval = 1;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);   

        timer.Start();
        Thread t = new Thread(ChangeTimerTest);
        t.Start();
    }

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine(System.DateTime.Now.ToLongTimeString());
    }

    private void ChangeTimerTest() {
        System.Diagnostics.Debug.WriteLine("thread run");
        timer.Interval = 2000;
    }

Hope this will finally help!

Nikola Davidovic
  • 8,556
  • 1
  • 27
  • 33