2

Got a quick question on creating a C# thread.

  • It needs to run every 10 minutes
  • The worker will do work then go into sleep for another 10 minutes
  • It can also be triggered to run immediately by calling Trigger()
  • It can be stopped by calling Stop()

I've created one with ManualResetEvent, which is set when Stop() is called. This works well but do I need to create another ManualResetEvent or wait handle in order to be able to trigger the worker immediately?

yyykk
  • 51
  • 2
  • 4

3 Answers3

7

If by Stop you mean Stop waiting and don't run again then I think a Threading.Timer will be a good (lean) choice.

You can activate a timer with a DoWork() method and a 10 minutes interval. It will use the ThreadPool which seems the best choice here. Trigger() can queue DoWork directly on the Pool and Stop() can deactivate the Timer. DoWork() shouldn't use Sleep() and be suitable for the ThreadPool.

H H
  • 263,252
  • 30
  • 330
  • 514
  • 1
    +1: This is probably a good way to go as long as you're doing work that is appropriate for a threadpool thread. Remember that thread pool threads aren't designed for long running activities. You wouldn't sleep the thread pool thread, you'd simply trigger the action every ten minutes with the appropriate manual manipulation of the timer on the manual Trigger(). – Greg D Jul 07 '09 at 12:10
1

Using a timer here makes sense. Here's a quick code-snippet which I haven't tested.

    private System.Timers.Timer _timer = null;

    public void Constructor()
    {
        _timer = new System.Timers.Timer(600000);
        _timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
    }

    public void ForceDoWork()
    {
        //unsubscribe to timer event, so work dowsnt get fired twice
        _timer.Elapsed -= new ElapsedEventHandler(t_Elapsed);

        StartWorking();

        _timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
    }

    public void StartWorking()
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(WorkToBeDone));
    }

    private void WorkToBeDone(object state)
    {
        //work here
    }

    public void t_Elapsed(object sender, ElapsedEventArgs e)
    {
        StartWorking();
    }
pavsaund
  • 696
  • 1
  • 5
  • 16
  • You are using separately created Threads, that is not as efficient as the ThreadPool. – H H Jul 07 '09 at 13:59
  • @Henk Very true, I didn't catch that one. Have a look at this SO post on Thread vs ThreadPool: http://stackoverflow.com/questions/230003/thread-vs-threadpool – pavsaund Jul 08 '09 at 08:43
  • @Paco Basicly, because Threading.Timer doesn't support registering and unregistering of listeners. Also Threading.Timer isn't threadsafe(!) as far as i know. ref: http://mark.michaelis.net/Blog/SystemWindowsFormsTimerVsSystemThreadingTimerVsSystemTimersTimer.aspx & http://msdn.microsoft.com/en-us/magazine/cc164015.aspx – pavsaund Jul 09 '09 at 09:02
0

Yes, you'll need another wait handle to force thread to execute. You'll basically have to WaitOne for this handle for 10 minutes, thus either elapsing a timeout or continuing whenever the wait handle becomes signalled.

Don't forget to switch that handle to a non-signalled state, though.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288