How to block a timer while processing the elapsed event?

后端 未结 5 1695
臣服心动
臣服心动 2021-02-13 09:00

I have a timer that needs to not process its elapsed event handler at the same time. But processing one Elapsed event may interfere with others. I implemented the bel

相关标签:
5条回答
  • 2021-02-13 09:31

    If LookForItWhichMightTakeALongTime() is going to take a long time, I would suggest not using a System.Windows.Forms.Timer because doing so will lock up your UI thread and the user may kill your application thinking that it has frozen.

    What you could use is a BackgroundWorker (along with a Timer if so desired).

    public class MyForm : Form
    {
      private BackgroundWorker backgroundWorker = new BackgroundWorker();
    
      public MyForm()
      {
        InitializeComponents();
        backgroundWorker.DoWork += backgroundWorker_DoWork;
        backgroundWorker.RunWorkerCompleted +=
                                    backgroundWorker_RunWorkerCompleted;
        backgroundWorker.RunWorkerAsync();
      }
    
      private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
      {
        e.Result = LookForItWhichMightTakeALongTime();
      }
    
      private void backgroundWorker_RunWorkerCompleted(object sender,
                                                 RunWorkerCompletedEventArgs e)
      {
        found = e.Result as MyClass;
      }
    }
    

    And you can call RunWorkerAsync() from anywhere you want to, even from a Timer if you want. And just make sure to check if the BackgroundWorker is running already since calling RunWorkerAsync() when it's running will throw an exception.

    private void timer_Tick(object sender, EventArgs e)
    {
      if (!backgroundWorker.IsBusy)
        backgroundWorker.RunWorkerAsync();
    }
    
    0 讨论(0)
  • 2021-02-13 09:31
    timer.enabled = false
    

    or

    timer.stop();
    

    and

    timer.enabled = true
    

    or

    timer.start();
    
    0 讨论(0)
  • 2021-02-13 09:33

    I use the System.Threading.Timer like so

     class Class1
        {
            static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));
    
            private static void DoSomething(object state)
            {
                timer = null; // stop timer
    
                // do some long stuff here
    
                timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
            }
    
    
    
        }
    
    0 讨论(0)
  • 2021-02-13 09:41

    You could set AutoReset to false, then explicitly reset the timer after you are done handling it. Of course, how you handle it really depends on how you expect the timer to operate. Doing it this way would allow your timer to drift away from the actual specified interval (as would stopping and restarting). Your mechanism would allow each interval to fire and be handled but it may result in a backlog of unhandled events that are handled now where near the expiration of the timer that cause the handler to be invoked.

    timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
    timer.Elapsed += Timer_OnElapsed;
    timer.AutoReset = false;
    timer.Start();
    
    
    public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
    {
        if (!found)
        {
          found = LookForItWhichMightTakeALongTime();
        }
        timer.Start();
    }
    
    0 讨论(0)
  • 2021-02-13 09:44

    I usually stop the timer while processing it, enter a try/finally block, and resume the timer when done.

    0 讨论(0)
提交回复
热议问题