C# Thread Synchronization - c#

I have a problem with C# threads.
I have eendless process “worker”, which do some and after iteration sleep 3 seconds.
I have a timer function that runs at a given time.
I need the "timer function" do something, then wait for the end "worker" iteration and then pause "worker" until "timer function" is done own task , after that timer function starts a "worker" again.
How can I do that?
Best regards Paul

You could use wait handles to control the methods - something like:
private AutoResetEvent mWorkerHandle = new AutoResetEvent(initialState: false);
private AutoResetEvent mTimerHandle = new AutoResetEvent(initialState: false);
// ... Inside method that initializes the threads
{
Thread workerThread = new Thread(new ThreadStart(Worker_DoWork));
Thread timerThread = new Thread(new ThreadStart(Timer_DoWork));
workerThread.Start();
timerThread.Start();
// Signal the timer to execute
mTimerHandle.Set();
}
// ... Example thread methods
private void Worker_DoWork()
{
while (true)
{
// Wait until we are signalled
mWorkerHandle.WaitOne();
// ... Perform execution ...
// Signal the timer
mTimerHandle.Set();
}
}
private void Timer_DoWork()
{
// Signal the worker to do something
mWorkerHandle.Set();
// Wait until we get signalled
mTimerHandle.WaitOne();
// ... Work has finished, do something ...
}
This should give you an idea of how to control methods running on other threads by way of a WaitHandle (in this case, an AutoResetEvent).

You can use a lock to pause a thread while another is doing something:
readonly object gate = new object();
void Timer()
{
// do something
...
// wait for the end "worker" iteration and then
// pause "worker" until "timer function" is done
lock (gate)
{
// do something more
...
}
// start the "worker" again
}
void Worker()
{
while (true)
{
lock (gate)
{
// do something
...
}
Thread.Sleep(3000);
}
}

Do you need paralel work of Worker and another operation? If not, You can do somthing similar:
EventWaitHandle processAnotherOperationOnNextIteration = new EventWaitHandle(false, EventResetMode.ManualReset);
Worker()
{
while(true)
{
doLongOperation();
if (processAnotherOperationOnNextIteration.WaitOne(0))
{
processAnotherOperationOnNextIteration.Reset();
doAnotherOperation();
}
Thread.Sleep(3000);
}
}
in timer
void Timer()
{
processAnotherOperationOnNextIteration.Set();
}

Related

Multi-thread when one thread is done and Suspend other threads

islem = new Thread(new ThreadStart(ilk));
islem2 = new Thread(new ThreadStart(ikinci));
islem3 = new Thread(new ThreadStart(ucuncu));
islem4 = new Thread(new ThreadStart(dorduncu));
islem.Start();
islem2.Start();
islem3.Start();
islem4.Start();
if (!islem.IsAlive)
{
islem2.Suspend();
islem3.Suspend();
islem4.Suspend();
}
I want to do when islem is done. Other threads suspend but it doesn't work
I read about ManualResetEvent but I can't figure out multi-threading examples.They works just one thread simples. Also I read http://www.albahari.com/threading/part4.aspx#_Suspending_and_Resuming this paper to and look similar questions like C# controlling threads (resume/suspend) How to pause/suspend a thread then continue it? Pause/Resume thread whith AutoResetEvent I am working multi - thread objects
If you just need to cancel the worker threads, the very simplest approach is to use a flag. You have to mark the flag volatile to ensure all threads are using the same copy.
private volatile bool _done = false;
void Main()
{
StartWorkerThreads();
}
void WorkerThread()
{
while (true)
{
if (_done) return; //Someone else solved the problem, so exit.
ContinueSolvingTheProblem();
}
_done = true; //Tell everyone else to stop working.
}
If you truly want to pause (I'm not sure why) you can use a ManualResetEvent. This allows blocking behavior without consuming resources for the paused thread.
//When signalled, indicates threads can proceed.
//When reset, threads should pause as soon as possible.
//Constructor argument = true so it is set by default
private ManualResetEvent _go = new ManualResetEvent(true);
void Main()
{
StartWorkerThreads();
}
void WorkerThread()
{
while (true)
{
_go.WaitOne(); //Pause if the go event has been reset
ContinueSolvingTheProblem();
}
_go.Reset(); //Reset the go event in order to pause the other threads
}
You can also combine the approaches, e.g. if you wanted to be able to pause the threads, do some more work, then cancel them:
private volatile bool _done = false;
private ManualResetEvent _go = new ManualResetEvent(true);
void Main()
{
StartWorkerThreads();
}
void WorkerThread()
{
while (true)
{
if (_done) return; //Exit if problem has been solved
_go.WaitOne(); //Pause if the go event has been reset
if (_done) return; //Exit if problem was solved while we were waiting
ContinueSolvingTheProblem();
}
_go.Reset(); //Reset the go event in order to pause the other threads
if (VerifyAnswer())
{
_done = true; //Set the done flag to indicate all threads should exit
}
else
{
_go.Set(); //Tell other threads to continue
}
}

See thread not correctly ended

I'm developing a project on Visual Studio 2015 using C# and WPF. Sometimes I quit my running project with my close command, and sometimes with the stop debug button. The problem is that after a few tests, my PC starts to warm and the fans make noise. I have to quit Visual Studio to calm the machine.
So I have questions :
How to see the threads not ended after a test ?
When I know them, how to properly end them ? (actually I Dispose some threads when WindowClosing)
How make sure that thread will properly ends when I use the stop debug button ?
Thank you
EDIT:
There is the screenshot of task manager. When I start application the CPU rise from 5% to 15% (or event 25%). RAM rise from 4GO to 4.5.
When I stop application, CPU goes to 45% for a few seconds and go back to 5% but RAM goes to 4.70GO and doesn't go back down.
EDIT2:
I founded this kind of thread on my application:
private bool isClosing = false;
public void Start()
{
isClosing = false;
ThreadPool.QueueUserWorkItem(new WaitCallback(doWorkThread));
}
public void Stop()
{
isClosing = true;
}
private AutoResetEvent endPoolStateButton = new AutoResetEvent(false);
private void doWorkThread(object sender)
{
Action action = new Action(() => doWork());
while (!isClosing)
{
Thread.Sleep(100);
this.Dispatcher.BeginInvoke(action, System.Windows.Threading.DispatcherPriority.Background);
}
endPoolStateButton.Set();
}
private void doWork()
{
/* Job performed */
}
I wonder if there is a really good way to use thread ? If application close without setting isClosing = true the while never stop. And the thread is never really aborted ? Do you think that this kind of thread can cause all the troubles I have ?
Here is my solution how to stop thread in elegant way. Hope the code is clear. I use CancellationToken to cancel operations in thread and ManualResetEvent to wait for thread cancellation:
namespace ElegantThreadWork
{
using System;
using System.Threading;
using System.Diagnostics;
class ThreadObject
{
public CancellationToken CancellationToken { get; private set; }
public ManualResetEvent WaitHandle { get; private set; }
public ThreadObject(CancellationToken ct, ManualResetEvent wh)
{
CancellationToken = ct;
WaitHandle = wh;
}
}
public class Program
{
static void DoWork(CancellationToken ct)
{
Console.WriteLine("Thread[{0}] started", Thread.CurrentThread.ManagedThreadId);
int i = 0;
// Check for cancellation on each iteration
while (!ct.IsCancellationRequested)
{
// Do something
Console.WriteLine("Thread[{0}]: {1}", Thread.CurrentThread.ManagedThreadId, i);
// Wait on CancellationToken. If cancel be called, WaitOne() will immediatly return control!
// You can see it by elapsed time
ct.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
i++;
}
Console.WriteLine("Thread[{0}] has been cancelled", Thread.CurrentThread.ManagedThreadId);
}
static void ThreadProc(object state)
{
ThreadObject to = (ThreadObject)state;
try
{
DoWork(to.CancellationToken);
}
finally
{
to.WaitHandle.Set();
}
}
public static void Main(string[] args)
{
TimeSpan MAX_THREAD_EXITING_TIMEOUT = TimeSpan.FromSeconds(5);
// Use for elegant thread exiting
ManualResetEvent isThreadExitedEvent = new ManualResetEvent(false);
CancellationTokenSource cts = new CancellationTokenSource();
ThreadObject threadObj = new ThreadObject(cts.Token, isThreadExitedEvent);
// Create thread
Thread thread = new Thread(ThreadProc, 0);
thread.Start(threadObj);
Console.WriteLine("Just do something in main thread");
Console.WriteLine("Bla.");
Thread.Sleep(1000);
Console.WriteLine("Bla..");
Thread.Sleep(1000);
Console.WriteLine("Bla...");
Thread.Sleep(1000);
Console.WriteLine("Thread cancelattion...");
Stopwatch sw = Stopwatch.StartNew();
// Cancel thread
cts.Cancel();
// Wait for thread exiting
var isOk = isThreadExitedEvent.WaitOne(MAX_THREAD_EXITING_TIMEOUT);
sw.Stop();
Console.WriteLine("Waiting {0} for thread exiting. Wait result: {1}. Cancelled in {2}", MAX_THREAD_EXITING_TIMEOUT, isOk, sw.Elapsed);
// If we couldn't stop thread in elegant way, just abort it
if (!isOk)
thread.Abort();
}
}
}
Maybe you can try to observe the behaviour of the process and the threads with the tool "Process Hacker". With this tool you get more detailed informations about the thread and you also can detect deamon threads.
Another way could be: Try to get all child threads of the main process and do something like
Thread t1; // specific child thread
t1.join();

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

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?
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;
}
}
You can disable and enable your timer in its elapsed callback.
public void TimerElapsed(object sender, EventArgs e)
{
_timer.Stop();
//Do Work
_timer.Start();
}
You can just use the System.Threading.Timer and just set the Timeout to Infinite before you process your data/method, then when it completes restart the Timer ready for the next call.
private System.Threading.Timer _timerThread;
private int _period = 2000;
public MainWindow()
{
InitializeComponent();
_timerThread = new System.Threading.Timer((o) =>
{
// Stop the timer;
_timerThread.Change(-1, -1);
// Process your data
ProcessData();
// start timer again (BeginTime, Interval)
_timerThread.Change(_period, _period);
}, null, 0, _period);
}
private void ProcessData()
{
// do stuff;
}
Using the PeriodicTaskFactory from my post here
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task task = PeriodicTaskFactory.Start(() =>
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(5000);
}, intervalInMilliseconds: 1000, synchronous: true, cancelToken: cancellationTokenSource.Token);
Console.WriteLine("Press any key to stop iterations...");
Console.ReadKey(true);
cancellationTokenSource.Cancel();
Console.WriteLine("Waiting for the task to complete...");
Task.WaitAny(task);
The output below shows that even though the interval is set 1000 milliseconds, each iteration doesn't start until the work of the task action is complete. This is accomplished using the synchronous: true optional parameter.
Press any key to stop iterations...
9/6/2013 1:01:52 PM
9/6/2013 1:01:58 PM
9/6/2013 1:02:04 PM
9/6/2013 1:02:10 PM
9/6/2013 1:02:16 PM
Waiting for the task to complete...
Press any key to continue . . .
UPDATE
If you want the "skipped event" behavior with the PeriodicTaskFactory simply don't use the synchronous option and implement the Monitor.TryEnter like what Bob did here https://stackoverflow.com/a/18665948/222434
Task task = PeriodicTaskFactory.Start(() =>
{
if (!Monitor.TryEnter(_locker)) { return; } // Don't let multiple threads in here at the same time.
try
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(5000);
}
finally
{
Monitor.Exit(_locker);
}
}, intervalInMilliseconds: 1000, synchronous: false, cancelToken: cancellationTokenSource.Token);
The nice thing about the PeriodicTaskFactory is that a Task is returned that can be used with all the TPL API, e.g. Task.Wait, continuations, etc.
This question already has a number of good answers, including a slightly newer one that is based on some of the features in the TPL. But I feel a lack here:
The TPL-based solution a) isn't really contained wholly here, but rather refers to another answer, b) doesn't show how one could use async/await to implement the timing mechanism in a single method, and c) the referenced implementation is fairly complicated, which somewhat obfuscates the underlying relevant point to this particular question.
The original question here is somewhat vague on the specific parameters of the desired implementation (though some of that is clarified in comments). At the same time, other readers may have similar but not identical needs, and no one answer addresses the variety of design options that might be desired.
I particularly like implementing periodic behavior using Task and async/await this way, because of the way it simplifies the code. The async/await feature in particular is so valuable in taking code that would otherwise be fractured by a continuation/callback implementation detail, and preserving its natural, linear logic in a single method. But no answer here demonstrates that simplicity.
So, with that rationale motivating me to add yet another answer to this question…
To me, the first thing to consider is "what exact behavior is desired here?" The question here starts with a basic premise: that the period task initiated by the timer should not run concurrently, even if the task takes longer than the timer period. But there are multiple ways that premise can be fulfilled, including:
Don't even run the timer while the task is running.
Run the timer (this and the remaining options I'm presenting here all assume the timer continues to run during the execution of the task), but if the task takes longer than the timer period, run the task again immediately after it's completed from the previous timer tick.
Only ever initiate execution of the task on a timer tick. If the task takes longer than the timer period, don't start a new task while the current one is executed, and even once the current one has completed, don't start a new one until the next timer tick.
If the task takes longer than the timer interval, not only run the task again immediately after it's completed, but run it as many times as necessary until the task has "caught up". I.e. over time, make a best effort to execute the task once for every timer tick.
Based on the comments, I have the impression that the #3 option most closely matches the OP's original request, though it sounds like the #1 option possibly would work too. But options #2 and #4 might be preferable to someone else.
In the following code example, I have implemented these options with five different methods (two of them implement option #3, but in slightly different ways). Of course, one would select the appropriate implementation for one's needs. You likely don't need all five in one program! :)
The key point is that in all of these implementations, they naturally and in a very simple way, execute the task in a period-but-non-concurrent way. That is, they effectively implement a timer-based execution model, while ensuring that the task is only ever being executed by one thread at a time, per the primary request of the question.
This example also illustrates how CancellationTokenSource can be used to interrupt the period task, taking advantage of await to handle the exception-based model in a clean, simple way.
class Program
{
const int timerSeconds = 5, actionMinSeconds = 1, actionMaxSeconds = 7;
static Random _rnd = new Random();
static void Main(string[] args)
{
Console.WriteLine("Press any key to interrupt timer and exit...");
Console.WriteLine();
CancellationTokenSource cancelSource = new CancellationTokenSource();
new Thread(() => CancelOnInput(cancelSource)).Start();
Console.WriteLine(
"Starting at {0:HH:mm:ss.f}, timer interval is {1} seconds",
DateTime.Now, timerSeconds);
Console.WriteLine();
Console.WriteLine();
// NOTE: the call to Wait() is for the purpose of this
// specific demonstration in a console program. One does
// not normally use a blocking wait like this for asynchronous
// operations.
// Specify the specific implementation to test by providing the method
// name as the second argument.
RunTimer(cancelSource.Token, M1).Wait();
}
static async Task RunTimer(
CancellationToken cancelToken, Func<Action, TimeSpan, Task> timerMethod)
{
Console.WriteLine("Testing method {0}()", timerMethod.Method.Name);
Console.WriteLine();
try
{
await timerMethod(() =>
{
cancelToken.ThrowIfCancellationRequested();
DummyAction();
}, TimeSpan.FromSeconds(timerSeconds));
}
catch (OperationCanceledException)
{
Console.WriteLine();
Console.WriteLine("Operation cancelled");
}
}
static void CancelOnInput(CancellationTokenSource cancelSource)
{
Console.ReadKey();
cancelSource.Cancel();
}
static void DummyAction()
{
int duration = _rnd.Next(actionMinSeconds, actionMaxSeconds + 1);
Console.WriteLine("dummy action: {0} seconds", duration);
Console.Write(" start: {0:HH:mm:ss.f}", DateTime.Now);
Thread.Sleep(TimeSpan.FromSeconds(duration));
Console.WriteLine(" - end: {0:HH:mm:ss.f}", DateTime.Now);
}
static async Task M1(Action taskAction, TimeSpan timer)
{
// Most basic: always wait specified duration between
// each execution of taskAction
while (true)
{
await Task.Delay(timer);
await Task.Run(() => taskAction());
}
}
static async Task M2(Action taskAction, TimeSpan timer)
{
// Simple: wait for specified interval, minus the duration of
// the execution of taskAction. Run taskAction immediately if
// the previous execution too longer than timer.
TimeSpan remainingDelay = timer;
while (true)
{
if (remainingDelay > TimeSpan.Zero)
{
await Task.Delay(remainingDelay);
}
Stopwatch sw = Stopwatch.StartNew();
await Task.Run(() => taskAction());
remainingDelay = timer - sw.Elapsed;
}
}
static async Task M3a(Action taskAction, TimeSpan timer)
{
// More complicated: only start action on time intervals that
// are multiples of the specified timer interval. If execution
// of taskAction takes longer than the specified timer interval,
// wait until next multiple.
// NOTE: this implementation may drift over time relative to the
// initial start time, as it considers only the time for the executed
// action and there is a small amount of overhead in the loop. See
// M3b() for an implementation that always executes on multiples of
// the interval relative to the original start time.
TimeSpan remainingDelay = timer;
while (true)
{
await Task.Delay(remainingDelay);
Stopwatch sw = Stopwatch.StartNew();
await Task.Run(() => taskAction());
long remainder = sw.Elapsed.Ticks % timer.Ticks;
remainingDelay = TimeSpan.FromTicks(timer.Ticks - remainder);
}
}
static async Task M3b(Action taskAction, TimeSpan timer)
{
// More complicated: only start action on time intervals that
// are multiples of the specified timer interval. If execution
// of taskAction takes longer than the specified timer interval,
// wait until next multiple.
// NOTE: this implementation computes the intervals based on the
// original start time of the loop, and thus will not drift over
// time (not counting any drift that exists in the computer's clock
// itself).
TimeSpan remainingDelay = timer;
Stopwatch swTotal = Stopwatch.StartNew();
while (true)
{
await Task.Delay(remainingDelay);
await Task.Run(() => taskAction());
long remainder = swTotal.Elapsed.Ticks % timer.Ticks;
remainingDelay = TimeSpan.FromTicks(timer.Ticks - remainder);
}
}
static async Task M4(Action taskAction, TimeSpan timer)
{
// More complicated: this implementation is very different from
// the others, in that while each execution of the task action
// is serialized, they are effectively queued. In all of the others,
// if the task is executing when a timer tick would have happened,
// the execution for that tick is simply ignored. But here, each time
// the timer would have ticked, the task action will be executed.
//
// If the task action takes longer than the timer for an extended
// period of time, it will repeatedly execute. If and when it
// "catches up" (which it can do only if it then eventually
// executes more quickly than the timer period for some number
// of iterations), it reverts to the "execute on a fixed
// interval" behavior.
TimeSpan nextTick = timer;
Stopwatch swTotal = Stopwatch.StartNew();
while (true)
{
TimeSpan remainingDelay = nextTick - swTotal.Elapsed;
if (remainingDelay > TimeSpan.Zero)
{
await Task.Delay(remainingDelay);
}
await Task.Run(() => taskAction());
nextTick += timer;
}
}
}
One final note: I came across this Q&A after following it as a duplicate of another question. In that other question, unlike here, the OP had specifically noted they were using the System.Windows.Forms.Timer class. Of course, this class is used mainly because it has the nice feature that the Tick event is raised in the UI thread.
Now, both it and this question involve a task that is actually executed in a background thread, so the UI-thread-affinitied behavior of that timer class isn't really of particular use in those scenarios. The code here is implemented to match that "start a background task" paradigm, but it can easily be changed so that the taskAction delegate is simply invoked directly, rather than being run in a Task and awaited. The nice thing about using async/await, in addition to the structural advantage I noted above, is that it preserves the thread-affinitied behavior that is desirable from the System.Windows.Forms.Timer class.
You can stop timer before the task and start it again after task completion this can make your take perform periodiacally on even interval of time.
public void myTimer_Elapsed(object sender, EventArgs e)
{
myTimer.Stop();
// Do something you want here.
myTimer.Start();
}
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.
There are at least 20 different ways to accomplish this, from using a timer and a semaphore, to volatile variables, to using the TPL, to using an opensource scheduling tool like Quartz etc al.
Creating a thread is an expensive exercise, so why not just create ONE and leave it running in the background, since it will spend the majority of its time IDLE, it causes no real drain on the system. Wake up periodically and do work, then go back to sleep for the time period. No matter how long the task takes, you will always wait at least the "waitForWork" timespan after completing before starting a new one.
//wait 5 seconds for testing purposes
static TimeSpan waitForWork = new TimeSpan(0, 0, 0, 5, 0);
static ManualResetEventSlim shutdownEvent = new ManualResetEventSlim(false);
static void Main(string[] args)
{
System.Threading.Thread thread = new Thread(DoWork);
thread.Name = "My Worker Thread, Dude";
thread.Start();
Console.ReadLine();
shutdownEvent.Set();
thread.Join();
}
public static void DoWork()
{
do
{
//wait for work timeout or shudown event notification
shutdownEvent.Wait(waitForWork);
//if shutting down, exit the thread
if(shutdownEvent.IsSet)
return;
//TODO: Do Work here
} while (true);
}
You can use System.Threading.Timer. Trick is to set the initial time only. Initial time is set again when previous interval is finished or when job is finished (this will happen when job is taking longer then the interval). Here is the sample code.
class Program
{
static System.Threading.Timer timer;
static bool workAvailable = false;
static int timeInMs = 5000;
static object o = new object();
static void Main(string[] args)
{
timer = new Timer((o) =>
{
try
{
if (workAvailable)
{
// do the work, whatever is required.
// if another thread is started use Thread.Join to wait for the thread to finish
}
}
catch (Exception)
{
// handle
}
finally
{
// only set the initial time, do not set the recurring time
timer.Change(timeInMs, Timeout.Infinite);
}
});
// only set the initial time, do not set the recurring time
timer.Change(timeInMs, Timeout.Infinite);
}
Why not use a timer with Monitor.TryEnter()? If OnTimerElapsed() is called again before the previous thread finishes, it will just be discarded and another attempt won't happen again until the timer fires again.
private static readonly object _locker = new object();
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
if (!Monitor.TryEnter(_locker)) { return; } // Don't let multiple threads in here at the same time.
try
{
// do stuff
}
finally
{
Monitor.Exit(_locker);
}
}
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.
lock
{
// this code will never be interrupted or started again until it has finished
}
This is a great way to be sure, your process will work until the end without interrupting.
If I understand you correctly, you actually just want to ensure your thread is not running before you dispatch another thread. Let's say you have a thread defined in your class like so.
private System.Threading.Thread myThread;
You can do:
//inside some executed method
System.Threading.Timer t = new System.Threading.Timer(timerCallBackMethod, null, 0, 5000);
then add the callBack like so
private void timerCallBackMethod(object state)
{
if(myThread.ThreadState == System.Threading.ThreadState.Stopped || myThread.ThreadState == System.Threading.ThreadState.Unstarted)
{
//dispatch new thread
}
}
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.
using System.Threading;
public class MyThread
{
public void ThreadFunc()
{
// do nothing apart from sleep a bit
System.Console.WriteLine("In Timer Function!");
Thread.Sleep(new TimeSpan(0, 0, 5));
}
};
class Program
{
static void Main(string[] args)
{
bool bExit = false;
DateTime tmeLastExecuted;
// while we don't have a condition to exit the thread loop
while (!bExit)
{
// create a new instance of our thread class and ThreadStart paramter
MyThread myThreadClass = new MyThread();
Thread newThread = new Thread(new ThreadStart(myThreadClass.ThreadFunc));
// just as well join the thread until it exits
tmeLastExecuted = DateTime.Now; // update timing flag
newThread.Start();
newThread.Join();
// when we are in the timing threshold to execute a new thread, we can exit
// this loop
System.Console.WriteLine("Sleeping for a bit!");
// only allowed to execute a thread every 10 seconds minimum
while (DateTime.Now - tmeLastExecuted < new TimeSpan(0, 0, 10));
{
Thread.Sleep(100); // sleep to make sure program has no tight loops
}
System.Console.WriteLine("Ok, going in for another thread creation!");
}
}
}
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
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 a ManualResetEvent (canExecute) that is initially set to be signalled in the StartTaskCallbacks method.
Note the way I use canExecute.WaitOne(0). The zero means that WaitOne will return immediately with the state of the WaitHandle (MSDN). If the zero is omitted, you would end up with every call to ExecuteTaskCallback 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 in StopTaskCallbacks 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 to canExecute.WaitOne(); will indeed cover the last task if there is one.
private static void ExecuteTaskCallback(object state)
{
ManualResetEvent canExecute = (ManualResetEvent)state;
if (canExecute.WaitOne(0))
{
canExecute.Reset();
Console.WriteLine("Doing some work...");
//Simulate doing work.
Thread.Sleep(3000);
Console.WriteLine("...work completed");
canExecute.Set();
}
else
{
Console.WriteLine("Returning as method is already running");
}
}
private static void StartTaskCallbacks()
{
ManualResetEvent canExecute = new ManualResetEvent(true),
stopRunning = new ManualResetEvent(false);
int interval = 1000;
//Periodic invocations. Begins immediately.
Timer timer = new Timer(ExecuteTaskCallback, canExecute, 0, interval);
//Simulate being stopped.
Timer stopTimer = new Timer(StopTaskCallbacks, new object[]
{
canExecute, stopRunning, timer
}, 10000, Timeout.Infinite);
stopRunning.WaitOne();
//Clean up.
timer.Dispose();
stopTimer.Dispose();
}
private static void StopTaskCallbacks(object state)
{
object[] stateArray = (object[])state;
ManualResetEvent canExecute = (ManualResetEvent)stateArray[0];
ManualResetEvent stopRunning = (ManualResetEvent)stateArray[1];
Timer timer = (Timer)stateArray[2];
//Stop the periodic invocations.
timer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("Waiting for existing work to complete");
canExecute.WaitOne();
stopRunning.Set();
}
I recommend to use Timer instead of thread, as it's lighter object. To achieve your goal you can do following.
using System.Timers;
namespace sample_code_1
{
public class ClassName
{
Timer myTimer;
static volatile bool isRunning;
public OnboardingTaskService()
{
myTimer= new Timer();
myTimer.Interval = 60000;
myTimer.Elapsed += myTimer_Elapsed;
myTimer.Start();
}
private void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (isRunning) return;
isRunning = true;
try
{
//Your Code....
}
catch (Exception ex)
{
//Handle Exception
}
finally { isRunning = false; }
}
}
}
Let me know if it helps.

How to terminate a worker thread correctly in c#

Problem statement
I have a worker thread that basically scans a folder, going into the files within it, and then sleeps for a while. The scanning operation might take 2-3 seconds but not much more. I'm looking for a way to stop this thread elegantly.
Clarification: I want to stop the thread while it's sleeping, and not while it's scanning. However, the problem is that I do not know what is the current state of the thread. If it's sleeping I want it to exit immediately. If it's scanning, I want it to exit the moment it tries to block.
Attempts at a solution
At first I was using Sleep and Interrupt. Then I found out that Interrupt doesn't really interrupt the Sleep - it only works when the threads TRIES to go into sleeping.
So I switched to Monitor Wait&Pulse. Then I found out that the Pulse only works when I'm actually in the Wait. So now I have a thread which looks like that:
while (m_shouldRun)
{
try
{
DoSomethingThatTakesSeveralSeconds();
lock (this)
{
Monitor.Wait(this, 5000);
}
}
catch (ThreadInterruptedException)
{
m_shouldRun = false;
}
}
And now I need to craft my Stop function. So I started with:
public void Stop()
{
m_shouldRun = false;
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
But this doesn't work because I may be pulsing while the thread works (while it's not waiting). So I added Interrupt:
public void Stop()
{
m_shouldRun = false;
thread.Interrupt();
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
Another option is to use:
public void Stop()
{
m_shouldRun = false;
while (!thread.Join(1000))
{
lock (this)
{
Monitor.Pulse(this);
}
}
}
The question
What is the preferred method? Is there a third method which is preferable?
Another alternative is to use events:
private ManualResetEvent _event = new ManualResetEvent(false);
public void Run()
{
while (true)
{
DoSomethingThatTakesSeveralSeconds();
if (_event.WaitOne(timeout))
break;
}
}
public void Stop()
{
_event.Set();
thread.Join();
}
The way to stop a thread elegantly is to leave it finish by itself. So inside the worker method you could have a boolean variable which will check whether we want to interrupt. By default it will be set to false and when you set it to true from the main thread it will simply stop the scanning operation by breaking from the processing loop.
I recommend to keep it simple:
while (m_shouldRun)
{
DoSomethingThatTakesSeveralSeconds();
for (int i = 0; i < 5; i++) // example: 5 seconds sleep
{
if (!m_shouldRun)
break;
Thread.Sleep(1000);
}
}
public void Stop()
{
m_shouldRun = false;
// maybe thread.Join();
}
This has the following advantages:
It smells like busy waiting, but it's not. $NUMBER_OF_SECONDS checks are done during the waiting phase, which is not comparable to the thousands of checks done in real busy waiting.
It's simple, which greatly reduces the risk of error in multi-threaded code. All your Stop method needs to do is to set m_shouldRun to false and (maybe) call Thread.Join (if it is necessary for the thread to finish before Stop is left). No synchronization primitives are needed (except for marking m_shouldRun as volatile).
I came up with separately scheduling the task:
using System;
using System.Threading;
namespace ProjectEuler
{
class Program
{
//const double cycleIntervalMilliseconds = 10 * 60 * 1000;
const double cycleIntervalMilliseconds = 5 * 1000;
static readonly System.Timers.Timer scanTimer =
new System.Timers.Timer(cycleIntervalMilliseconds);
static bool scanningEnabled = true;
static readonly ManualResetEvent scanFinished =
new ManualResetEvent(true);
static void Main(string[] args)
{
scanTimer.Elapsed +=
new System.Timers.ElapsedEventHandler(scanTimer_Elapsed);
scanTimer.Enabled = true;
Console.ReadLine();
scanningEnabled = false;
scanFinished.WaitOne();
}
static void scanTimer_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
scanFinished.Reset();
scanTimer.Enabled = false;
if (scanningEnabled)
{
try
{
Console.WriteLine("Processing");
Thread.Sleep(5000);
Console.WriteLine("Finished");
}
finally
{
scanTimer.Enabled = scanningEnabled;
scanFinished.Set();
}
}
}
}
}

Synchronizing a timer to prevent overlap

I'm writing a Windows service that runs a variable length activity at intervals (a database scan and update). I need this task to run frequently, but the code to handle isn't safe to run multiple times concurrently.
How can I most simply set up a timer to run the task every 30 seconds while never overlapping executions? (I'm assuming System.Threading.Timer is the correct timer for this job, but could be mistaken).
You could do it with a Timer, but you would need to have some form of locking on your database scan and update. A simple lock to synchronize may be enough to prevent multiple runs from occurring.
That being said, it might be better to start a timer AFTER your operation is complete, and just use it one time, then stop it. Restart it after your next operation. This would give you 30 seconds (or N seconds) between events, with no chance of overlaps, and no locking.
Example :
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((g) =>
{
Console.WriteLine(1); //do whatever
timer.Change(5000, Timeout.Infinite);
}, null, 0, Timeout.Infinite);
Work immediately .....Finish...wait 5 sec....Work immediately .....Finish...wait 5 sec....
I'd use Monitor.TryEnter in your elapsed code:
if (Monitor.TryEnter(lockobj))
{
try
{
// we got the lock, do your work
}
finally
{
Monitor.Exit(lockobj);
}
}
else
{
// another elapsed has the lock
}
I prefer System.Threading.Timer for things like this, because I don't have to go through the event handling mechanism:
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);
object updateLock = new object();
void UpdateCallback(object state)
{
if (Monitor.TryEnter(updateLock))
{
try
{
// do stuff here
}
finally
{
Monitor.Exit(updateLock);
}
}
else
{
// previous timer tick took too long.
// so do nothing this time through.
}
}
You can eliminate the need for the lock by making the timer a one-shot and re-starting it after every update:
// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);
void UpdateCallback(object state)
{
// do stuff here
// re-enable the timer
UpdateTimer.Change(30000, Timeout.Infinite);
}
instead of locking (which could cause all of your timed scans to wait and eventually stack up). You could start the scan/update in a thread and then just do a check to see if the thread is still alive.
Thread updateDBThread = new Thread(MyUpdateMethod);
...
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!updateDBThread.IsAlive)
updateDBThread.Start();
}
Starting from .NET 6 there is a new timer available, the PeriodicTimer. This is a lightweight async-enabled timer, that becomes the perfect tool when overlapping executions should be strictly forbidden. You use this timer by writing an asynchronous method with a loop, and invoking it to start the loop:
private Task _operation;
private CancellationTokenSource _operationCancellation = new();
//...
_operation = StartTimer();
//...
private async Task StartTimer()
{
PeriodicTimer timer = new(TimeSpan.FromSeconds(30));
while (true)
{
await timer.WaitForNextTickAsync(_operationCancellation.Token);
try
{
DoSomething();
}
catch (Exception ex)
{
_logger.LogError(ex);
}
}
}
Instead of using a CancellationTokenSource, you can also stop the loop by disposing the PeriodicTimer. In this case the await timer.WaitForNextTickAsync() will return false.
It is possible that the DoSomething will be invoked subsequently with smaller interval than 30 seconds, but it's impossible that it will be invoked in overlapping fashion, unless you start accidentally two asynchronous loops.
This timer does not support disabling and reenabling it. If you need this functionality you could look at the third-party Nito.AsyncEx.PauseTokenSource component.
In case you are targeting a .NET version earlier than .NET 6, you could look at this question for an alternative: Run async method regularly with specified interval.
You could use the AutoResetEvent as follows:
// Somewhere else in the code
using System;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(30000, false))
{
// Signalled time to quit
return;
}
else
{
// grab a lock
// do the work
// Whatever...
}
}
}
A slightly "smarter" solution is as follow in pseudo-code:
using System;
using System.Diagnostics;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
Stopwatch stopWatch = new Stopwatch();
TimeSpan Second30 = new TimeSpan(0,0,30);
TimeSpan SecondsZero = new TimeSpan(0);
TimeSpan waitTime = Second30 - SecondsZero;
TimeSpan interval;
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(waitTime, false))
{
// Signalled time to quit
return;
}
else
{
stopWatch.Start();
// grab a lock
// do the work
// Whatever...
stopwatch.stop();
interval = stopwatch.Elapsed;
if (interval < Seconds30)
{
waitTime = Seconds30 - interval;
}
else
{
waitTime = SecondsZero;
}
}
}
}
Either of these has the advantage that you can shutdown the thread, just by signaling the event.
Edit
I should add, that this code makes the assumption that you only have one of these MyWorkerThreads() running, otherwise they would run concurrently.
I've used a mutex when I've wanted single execution:
private void OnMsgTimer(object sender, ElapsedEventArgs args)
{
// mutex creates a single instance in this application
bool wasMutexCreatedNew = false;
using(Mutex onlyOne = new Mutex(true, GetMutexName(), out wasMutexCreatedNew))
{
if (wasMutexCreatedNew)
{
try
{
//<your code here>
}
finally
{
onlyOne.ReleaseMutex();
}
}
}
}
Sorry I'm so late...You will need to provide the mutex name as part of the GetMutexName() method call.

Categories

Resources