Can I use a lock with this ManualResetEvent to ensure thread safety? - c#

Say I have two functions that manipulate a count, and an OnTimer function that fires at a regular interval.
void IncrementCount()
{
_myCount++;
}
void OverwriteCount(int newValue)
{
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
}
My desire is that if/when OverwriteCount is called, IncrementCount can't be executed until the timer function executes.
My initial thought to resolve this was to use a ManualResetEvent to help synchronize behaviors:
private static ManualResetEventSlim mre = new ManualResetEventSlim(initialState: true);
void IncrementCount()
{
mre.Wait(-1); // can't increment until the event is signaled
_myCount++;
}
void OverwriteCount(int newValue)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
My concern is a degenerate, multi-threaded scenario where thread A gets past the mre.Wait() in IncrementCount() but hasn't actually incremented _myCount yet. Thread B then calls mre.Reset() and overwrites _myCount. Thread A then gets a turn and increments _myCount.
Could I solve this by also adding a lock inside IncrementCount() and OverwriteCount() to ensure only one thread can modify _myCount at a time? Do I risk deadlock if I get stuck waiting on the reset event while holding the lock?

If i understand you, then yes it would work if you chose what to lock appropriately. There is probably a more granular way to do this, but as of now i see nothing wrong with this
void IncrementCount()
{
mre.Wait();
// lets not cause a race, lock until OverwriteCount is finished
lock (_sync)
{
_myCount++;
}
}
void OverwriteCount(int newValue)
{
// lock this so we can assure the count is updated
lock (_sync)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
}
void OnTimer()
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}

Related

Is this lock + ManualResetEvent usage thread safe?

This is a separate question based off of this question. To recap, say I have two functions that manipulate a count, and an OnTimer function that fires at a regular interval. My desire is that if/when OverwriteCount is called, IncrementCount can't be executed until the timer function executes.
The proposed solution was:
private int _myCount = 0;
private readonly object _sync = new object();
private ManualResetEventSlim mre = new ManualResetEventSlim(initialState: true);
void IncrementCount()
{
mre.Wait(); // all threads wait until the event is signaled
lock (_sync)
{
_myCount++;
}
}
void OverwriteCount(int newValue)
{
lock (_sync)
{
mre.Reset(); // unsignal the event, blocking threads
_myCount = newValue;
}
}
void OnTimer()
{
lock (_sync)
{
Console.WriteLine(_myCount);
mre.Set(); // signal the event
}
}
The ManualResetEventSlim tries to ensure that once OverwriteCount() unsignals the event, any modifications to _myCount must wait until OnTimer() executes.
Problem:
Say thread A enters IncrementCount() and passes the event's wait() - the ManualResetEvent's initial state is already signaled.
Thread B then starts and executes all of OverwriteCount().
Thread A then continues by acquiring the lock and incrementing _myCount.
This violates my goal as _myCount would change after a call to OverwriteCount(), prior to OnTimer running.
Rejected Alternative: I could move mre.Wait() within lock(_sync) but that poses a deadlock risk. If thread A calls IncrementCount() and blocks on the wait, no other threads can acquire the lock to release it.
Question: Do I need a different synchronization primitive to achieve my goal? Alternatively, am I wrong about the thread safety concern?
I think you can achieve your goal with just the standard Monitor and an additional flag.
private readonly object _sync = new object();
private int _myCount = 0;
private bool _canIncrement = true;
void IncrementCount()
{
lock (_sync)
{
// If the flag indicates we can't increment, unlock _sync and wait for a pulse.
// Use a loop here to ensure that if Wait() returns following the PulseAll() below
// (after re-acquiring the lock on _sync), but a call to OverwriteCount managed to
// occur in-between, that we wait again.
while (!_canIncrement)
{
Monitor.Wait(_sync);
}
_myCount++;
}
}
void OverwriteCount(int newValue)
{
lock (_sync)
{
_canIncrement = false;
_myCount = newValue;
}
}
void OnTimer()
{
lock (_sync)
{
Console.WriteLine(_myCount);
_canIncrement = true;
// Ready any threads waiting on _sync in IncrementCount() above
Monitor.PulseAll(_sync);
}
}

How to stop a System.Threading.Timer and cancel any callback that is running?

Example of my code:
Timer timer = new Timer(Timer_Tick, null, Timeout.Infinite, Timeout.Infinite);
Mutex timerSync = new Mutex();
void StartWork()
{
timer.Change(0, 1); //Start timer
//Do something...
}
void Dispose()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //Stop timer
timer.Dispose();
timerSync.Dispose();
//Dispose other things...
}
void Timer_Tick()
{
if (timerSync.WaitOne(0))
{
try
{
//Do something...
}
catch (Exception)
{
//If any exception occurs, abort the "Tick" callback!
return;
}
finally
{
//Whatever happens, release the mutex!
timerSync.ReleaseMutex();
}
}
}
When I stop the timer and dispose it, this not stops the current callback, that generates errors.
In particular, if a callback is in running, I get an ObjectDisposedException related to the mutex.
For the way the execution is structured, if I use that mutex on "Dispose" method, this causes a deadlock.
I have already thought of a solution: Use another try-catch block to handle exceptions related to the mutex.
But I want to know if there is a method to force to cancel any callback of the timer when it is disposed.
According to the documentation, you should use the Dispose(WaitHandle) overload:
Releases all resources used by the current instance of Timer and signals when the timer has been disposed of.
When this method completes, it signals the WaitHandle specified by the notifyObject parameter.Use this overload of the Dispose method if you want to be able to block until you are certain that the timer has been disposed. The timer is not disposed until all currently queued callbacks have completed.
void Dispose()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //Stop timer
var waiter = new ManualResetEvent(false);
timer.Dispose(waiter);
waiter.WaitOne();
waiter.Dispose();
timerSync.Dispose();
//Dispose other things...
}
If you don't want to wait for the current callback to be executed at all, you could follow the IDisposable pattern:
Timer timer = new Timer(Timer_Tick, null, Timeout.Infinite, Timeout.Infinite);
Mutex timerSync = new Mutex();
private bool _disposed;
void Dispose()
{
_disposed = true;
...
}
void Timer_Tick()
{
if (_disposed)
{
return;
}
...
}

How to ensure timer is fully paused?

Assume we have this event attached to the timer event handler.
private void TimerTick(object sender, ElapsedEventArgs e)
{
if(_gaurd) return;
lock (this) // lock per instance
{
_gaurd = true;
if (!_timer.Enabled) return;
OnTick(); // somewhere inside here timer may pause it self.
_gaurd = false;
}
}
Now there two things that can pause this timer. One is user request from UI thread, second is the timer which may pause it self.
If the timer pause it self we can guarantee the pause will complete before we continue.
timer.Stop();
OnPause(); // timer must be paused because OnPause() is not thread safe.
But if the user, requests for timer pause the request is from another thread and we can not guarantee timer is fully paused or not.
timer.Stop();
OnPause(); // timer event may be still inside OnTick() and may conflict with OnPause()
-------------------------------------------------------------------------------------------------------
So I'm looking for a way to make this thread safe. This is what I have tried so far but I'm not sure if this works in all situations or not.
Its looking good but want to make sure that if there is anything I'm not aware of. or maybe to know if there are better ways to make this process thread safe.
I have tried to separate user request from Inner workings of timer. therefore I have two Pause methods for my timer.
public class Timer
{
internal void InternalStop() // must be called by timer itself.
{
timer.Pause(); // causes no problem
}
public void Stop() // user request must come here. (if timer call this deadlock happens)
{
InternalStop();
lock (this) // reference of timer
{
// do nothing and wait for OnTick().
}
}
}
This is not actual code but behavior is same. it should illustrate that this class is not thread safe. :
public class WorkingArea
{
private List<Worker> _workers;
public void OnTick()
{
foreach(var worker in _workers)
{
worker.Start();
}
if(_workers.TrueForAll(w => w.Ends))
{
PauseTimer();
}
}
public void OnPause() // after timer paused
{
foreach(var Worker in _workers)
{
worker.Stop();
}
}
}
My timer was already thread safe.
it was all about the fact that I didn't know about Re-entrant locks
So if user from another thread request to pause timer , lock will work just fine and will block until timer is fully paused.
If the timer internally pauses it self it wont deal lock. because its in the same thread the lock was acquired.
public class Timer
{
private timer = new System.Timers.Timer();
private bool _guard = false;
// stops the timer and waits until OnTick returns and lock releases.
// timer can safely pause it self within OnTick.
// if user request to pause from another thread, full pause is ensured
public void Stop()
{
timer.Pause();
lock (this) // reference of timer. it wont dead lock
{
// do nothing and wait for OnTick().
}
}
private void TimerTick(object sender, ElapsedEventArgs e)
{
if(_gaurd) return;
lock (this) // lock per instance
{
_gaurd = true;
if (!_timer.Enabled) return;
OnTick(); // somewhere inside here timer may pause it self.
_gaurd = false;
}
}
}

Reliably stop System.Threading.Timer?

Well I've searched a lot for a solution to this. I'm looking for a clean and simple way to prevent the callback method of a System.Threading.Timer from being invoked after I've stopped it.
I can't seem to find any, and this has led me, on occassion, to resort to the dreaded thread-thread.sleep-thread.abort combo.
Can it be done using lock?
An easier solution might to be to set the Timer never to resume; the method Timer.Change can take values for dueTime and period that instruct the timer never to restart:
this.Timer.Change(Timeout.Infinite, Timeout.Infinite);
Whilst changing to use System.Timers.Timer might be a "better" solution, there are always going to be times when that's not practical; just using Timeout.Infinite should suffice.
like Conrad Frix suggested you should use the System.Timers.Timer class instead, like:
private System.Timers.Timer _timer = new System.Timers.Timer();
private volatile bool _requestStop = false;
public constructor()
{
_timer.Interval = 100;
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = false;
_timer.Start();
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// do work....
if (!_requestStop)
{
_timer.Start();//restart the timer
}
}
private void Stop()
{
_requestStop = true;
_timer.Stop();
}
private void Start()
{
_requestStop = false;
_timer.Start();
}
The MSDN Docs suggest that you use the Dispose(WaitHandle) method to stop the timer + be informed when callbacks will no longer be invoked.
For the System.Threading.Timer one can do the following (Will also protect the callback-method from working on a disposed timer - ObjectDisposedException):
class TimerHelper : IDisposable
{
private System.Threading.Timer _timer;
private readonly object _threadLock = new object();
public event Action<Timer,object> TimerEvent;
public void Start(TimeSpan timerInterval, bool triggerAtStart = false,
object state = null)
{
Stop();
_timer = new System.Threading.Timer(Timer_Elapsed, state,
System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
if (triggerAtStart)
{
_timer.Change(TimeSpan.FromTicks(0), timerInterval);
}
else
{
_timer.Change(timerInterval, timerInterval);
}
}
public void Stop(TimeSpan timeout = TimeSpan.FromMinutes(2))
{
// Wait for timer queue to be emptied, before we continue
// (Timer threads should have left the callback method given)
// - http://woowaabob.blogspot.dk/2010/05/properly-disposing-systemthreadingtimer.html
// - http://blogs.msdn.com/b/danielvl/archive/2011/02/18/disposing-system-threading-timer.aspx
lock (_threadLock)
{
if (_timer != null)
{
ManualResetEvent waitHandle = new ManualResetEvent(false)
if (_timer.Dispose(waitHandle))
{
// Timer has not been disposed by someone else
if (!waitHandle.WaitOne(timeout))
throw new TimeoutException("Timeout waiting for timer to stop");
}
waitHandle.Close(); // Only close if Dispose has completed succesful
_timer = null;
}
}
}
public void Dispose()
{
Stop();
TimerEvent = null;
}
void Timer_Elapsed(object state)
{
// Ensure that we don't have multiple timers active at the same time
// - Also prevents ObjectDisposedException when using Timer-object
// inside this method
// - Maybe consider to use _timer.Change(interval, Timeout.Infinite)
// (AutoReset = false)
if (Monitor.TryEnter(_threadLock))
{
try
{
if (_timer==null)
return;
Action<Timer, object> timerEvent = TimerEvent;
if (timerEvent != null)
{
timerEvent(_timer, state);
}
}
finally
{
Monitor.Exit(_threadLock);
}
}
}
}
This is how one can use it:
void StartTimer()
{
TimerHelper _timerHelper = new TimerHelper();
_timerHelper.TimerEvent += (timer,state) => Timer_Elapsed();
_timerHelper.Start(TimeSpan.FromSeconds(5));
System.Threading.Sleep(TimeSpan.FromSeconds(12));
_timerHelper.Stop();
}
void Timer_Elapsed()
{
// Do what you want to do
}
For what it's worth, we use this pattern quite a bit:
// set up timer
Timer timer = new Timer(...);
...
// stop timer
timer.Dispose();
timer = null;
...
// timer callback
{
if (timer != null)
{
..
}
}
This answer relates to System.Threading.Timer
I've read a lot of nonsense about how to synchronize disposal of System.Threading.Timer all over the net. So that's why I'm posting this in an attempt to rectify the situation somewhat. Feel free to tell me off / call me out if something I'm writing is wrong ;-)
Pitfalls
In my opinion there's these pitfalls:
Timer.Dispose(WaitHandle) can return false. It does so in case it's already been disposed (I had to look at the source code). In that case it won't set the WaitHandle - so don't wait on it!
not handling a WaitHandle timeout. Seriously - what are you waiting for in case you're not interested in a timeout?
Concurrency issue as mentioned here on msdn where an ObjectDisposedException can occur during (not after) disposal.
Timer.Dispose(WaitHandle) does not work properly with -Slim waithandles, or not as one would expect. For example, the following does not work (it blocks forever):
using(var manualResetEventSlim = new ManualResetEventSlim)
{
timer.Dispose(manualResetEventSlim.WaitHandle);
manualResetEventSlim.Wait();
}
Solution
Well the title is a bit "bold" i guess, but below is my attempt to deal with the issue - a wrapper which handles double-disposal, timeouts, and ObjectDisposedException. It does not provide all of the methods on Timer though - but feel free to add them.
internal class Timer
{
private readonly TimeSpan _disposalTimeout;
private readonly System.Threading.Timer _timer;
private bool _disposeEnded;
public Timer(TimeSpan disposalTimeout)
{
_disposalTimeout = disposalTimeout;
_timer = new System.Threading.Timer(HandleTimerElapsed);
}
public event Action Elapsed;
public void TriggerOnceIn(TimeSpan time)
{
try
{
_timer.Change(time, Timeout.InfiniteTimeSpan);
}
catch (ObjectDisposedException)
{
// race condition with Dispose can cause trigger to be called when underlying
// timer is being disposed - and a change will fail in this case.
// see
// https://msdn.microsoft.com/en-us/library/b97tkt95(v=vs.110).aspx#Anchor_2
if (_disposeEnded)
{
// we still want to throw the exception in case someone really tries
// to change the timer after disposal has finished
// of course there's a slight race condition here where we might not
// throw even though disposal is already done.
// since the offending code would most likely already be "failing"
// unreliably i personally can live with increasing the
// "unreliable failure" time-window slightly
throw;
}
}
}
private void HandleTimerElapsed(object state)
{
Elapsed?.Invoke();
}
public void Dispose()
{
var waitHandle = new ManualResetEvent(false));
// returns false on second dispose
if (_timer.Dispose(waitHandle))
{
if (waitHandle.WaitOne(_disposalTimeout))
{
_disposeEnded = true;
waitHandle.Dispose();
}
else
{
// don't dispose the wait handle, because the timer might still use it.
// Disposing it might cause an ObjectDisposedException on
// the timer thread - whereas not disposing it will
// result in the GC cleaning up the resources later
throw new TimeoutException(
"Timeout waiting for timer to stop. (...)");
}
}
}
}
You can't guarantee that your code that supposed to stop the timer will execute before timer event invocation.
For example, suppose on time moment 0 you initialized timer to call event when time moment 5 comes. Then on time moment 3 you decided that you no longer needed the call. And called method you want to write here. Then while method was JIT-ted comes time moment 4 and OS decides that your thread exhaust its time slice and switch. And timer will invoke the event no matter how you try - your code just won't have a chance to run in worst case scenario.
That's why it is safer to provide some logic in the event handler. Maybe some ManualResetEvent that will be Reset as soon as you no longer needed event invocation. So you Dispose the timer, and then set the ManualResetEvent. And in the timer event handler first thing you do is test ManualResetEvent. If it is in reset state - just return immediately. Thus you can effectively guard against undesired execution of some code.
To me, this seems to be the correct way to go:
Just call dispose when you are done with the timer. That will stop the timer and prevent future scheduled calls.
See example below.
class Program
{
static void Main(string[] args)
{
WriteOneEverySecond w = new WriteOneEverySecond();
w.ScheduleInBackground();
Console.ReadKey();
w.StopTimer();
Console.ReadKey();
}
}
class WriteOneEverySecond
{
private Timer myTimer;
public void StopTimer()
{
myTimer.Dispose();
myTimer = null;
}
public void ScheduleInBackground()
{
myTimer = new Timer(RunJob, null, 1000, 1000);
}
public void RunJob(object state)
{
Console.WriteLine("Timer Fired at: " + DateTime.Now);
}
}
Perhaps you should do the opposite. Use system.timers.timer, set the AutoReset to false and only Start it when you want to
You can stop a timer by creating a class like this and calling it from, for example, your callback method:
public class InvalidWaitHandle : WaitHandle
{
public IntPtr Handle
{
get { return InvalidHandle; }
set { throw new InvalidOperationException(); }
}
}
Instantiating timer:
_t = new Timer(DisplayTimerCallback, TBlockTimerDisplay, 0, 1000);
Then inside callback method:
if (_secondsElapsed > 80)
{
_t.Dispose(new InvalidWaitHandle());
}
There is a MSDN link how to achieve stop timer correctly. Use ControlThreadProc() method with HandleElapsed(object sender, ElapsedEventArgs e) event synchronized by syncPoint static class variable. Comment out Thread.Sleep(testRunsFor); on ControlThreadProc() if it is not suitable(probably).
The key is there that using static variable and an atomic operation like Interlocked.CompareExchange on conditional statements.
Link :
Timer.Stop Method

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();
}
}
}
}
}

Categories

Resources