views:

454

answers:

3

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?

A: 

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
+7  A: 

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.

Henk Holterman
+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
+1  A: 

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
You are using separately created Threads, that is not as efficient as the ThreadPool.
Henk Holterman
@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
Why a System.Timer instead of a Threading.Timer?
Paco
pavsaund