Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# run a thread every X minutes, but only if that thread is not running already

Tags:

c#

timer

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?

like image 360
Keith Palmer Jr. Avatar asked Sep 24 '12 17:09

Keith Palmer Jr.


People also ask

What C is used for?

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 in C language?

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.

What is the full name of C?

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.

Is C language easy?

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.


2 Answers

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).

like image 142
Grx70 Avatar answered Sep 27 '22 20:09

Grx70


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;     } } 
like image 44
Matt Johnson-Pint Avatar answered Sep 27 '22 20:09

Matt Johnson-Pint