I have a C# program that needs to dispatch a thread every X minutes, but only if the previously dispatched thread (from X minutes) ago is not currently still running.
A plain old Timer
alone will not work (because it dispatches an event every X minutes regardless or whether or not the previously dispatched process has finished yet).
The process that's going to get dispatched varies wildly in the time it takes to perform it's task - sometimes it might take a second, sometimes it might take several hours. I don't want to start the process again if it's still processing from the last time it was started.
Can anyone provide some working C# sample code?
The guts of this is the
ExecuteTaskCallback
method. This bit is charged with doing some work, but only if it is not already doing so. For this I have used aManualResetEvent
(canExecute
) that is initially set to be signalled in theStartTaskCallbacks
method.Note the way I use
canExecute.WaitOne(0)
. The zero means thatWaitOne
will return immediately with the state of theWaitHandle
(MSDN). If the zero is omitted, you would end up with every call toExecuteTaskCallback
eventually running the task, which could be fairly disastrous.The other important thing is to be able to end processing cleanly. I have chosen to prevent the
Timer
from executing any further methods inStopTaskCallbacks
because it seems preferable to do so while other work may be ongoing. This ensures that both no new work will be undertaken, and that the subsequent call tocanExecute.WaitOne();
will indeed cover the last task if there is one.If you want the timer's callback to fire on a background thread, you could use a System.Threading.Timer. This Timer class allows you to "Specify
Timeout.Infinite
to disable periodic signaling." as part of the constructor, which causes the timer to fire only a single time.You can then construct a new timer when your first timer's callback fires and completes, preventing multiple timers from being scheduled until you are ready for them to occur.
The advantage here is you don't create timers, then cancel them repeatedly, as you're never scheduling more than your "next event" at a time.
I had the same problem some time ago and all I had done was using the lock{} statement. With this, even if the Timer wants to do anything, he is forced to wait, until the end of the lock-Block.
i.e.
This is a great way to be sure, your process will work until the end without interrupting.
In my opinion the way to go in this situation is to use
System.ComponentModel.BackgroundWorker
class and then simply check itsIsBusy
property each time you want to dispatch (or not) the new thread. The code is pretty simple; here's an example:In this example I used
System.Timers.Timer
, but I believe it should also work with other timers. TheBackgroundWorker
class also supports progress reporting and cancellation, and uses event-driven model of communication with the dispatching thread, so you don't have to worry about volatile variables and the like...EDIT
Here's more elaborate example including cancelling and progress reporting:
Then, in order to cancel further execution simply call
worker.CancelAsync()
. Note that this is completely user-handled cancellation mechanism (it does not support thread aborting or anything like that out-of-the-box).You can just maintain a volatile bool to achieve what you asked:
This should do what you want. It executes a thread, then joins the thread until it has finished. Goes into a timer loop to make sure it is not executing a thread prematurely, then goes off again and executes.
Should produce something like:
In Timer Function! Sleeping for a bit! Ok, going in for another thread creation! In Timer Function! Sleeping for a bit! Ok, going in for another thread creation! In Timer Function! ... ...
Hope this helps! SR