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?
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
In my opinion the way to go in this situation is to use System.ComponentModel.BackgroundWorker
class and then simply check its IsBusy
property each time you want to dispatch (or not) the new thread. The code is pretty simple; here's an example:
class MyClass { private BackgroundWorker worker; public MyClass() { worker = new BackgroundWorker(); worker.DoWork += worker_DoWork; Timer timer = new Timer(1000); timer.Elapsed += timer_Elapsed; timer.Start(); } void timer_Elapsed(object sender, ElapsedEventArgs e) { if(!worker.IsBusy) worker.RunWorkerAsync(); } void worker_DoWork(object sender, DoWorkEventArgs e) { //whatever You want the background thread to do... } }
In this example I used System.Timers.Timer
, but I believe it should also work with other timers. The BackgroundWorker
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:
class MyClass { private BackgroundWorker worker; public MyClass() { worker = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; worker.DoWork += worker_DoWork; worker.ProgressChanged += worker_ProgressChanged; worker.RunWorkerCompleted += worker_RunWorkerCompleted; Timer timer = new Timer(1000); timer.Elapsed += timer_Elapsed; timer.Start(); } void timer_Elapsed(object sender, ElapsedEventArgs e) { if(!worker.IsBusy) worker.RunWorkerAsync(); } void worker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker w = (BackgroundWorker)sender; while(/*condition*/) { //check if cancellation was requested if(w.CancellationPending) { //take any necessary action upon cancelling (rollback, etc.) //notify the RunWorkerCompleted event handler //that the operation was cancelled e.Cancel = true; return; } //report progress; this method has an overload which can also take //custom object (usually representing state) as an argument w.ReportProgress(/*percentage*/); //do whatever You want the background thread to do... } } void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { //display the progress using e.ProgressPercentage and/or e.UserState } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if(e.Cancelled) { //do something } else { //do something else } } }
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:
private volatile bool _executing; private void TimerElapsed(object state) { if (_executing) return; _executing = true; try { // do the real work here } catch (Exception e) { // handle your error } finally { _executing = false; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With