Thread is getting stuck in a Lock - c#

I have the following scenario:
A thread pool of 3 threads, and each one of them should pick from a list of 9 operations randomly. Between that nine operations there are two which can't be performed at the same time, so I'm using a lock in those 2 methods (operations) like below:
private Object lockThis6 = new Object();
private Object lockThis7 = new Object();
public void OpSix(uSupervisor supervisor)
{
lock (lockThis6)
{
try
{
//Intructions
//Event Handler
OnOpFinished(supervisor);
}
catch
{
}
}
}
public void OpSeven(uSupervisor supervisor)
{
lock (lockThis7)
{
try
{
//Intructions
//Event Handler
OnOpFinished(supervisor);
}
catch
{
}
}
}
//EventHandler
protected virtual void OnOpFinished(uSupervisor supervisor)
{
if (OpFinished != null)
OpFinished(this, new EventLoad(supervisor));
}
In the end of the Instruction, an event is raised to "Inform" the thread to pick an operation randomly.
Misteriously sometimes the Threads are getting stuck in the lock statement, I was trying to figure it out if it's a dead lock scenario but It's not the case

The problem in my code is in the Event Handler. Due to the fact that the Event Handler is called inside the Lock statement, the Lock will always be locked for any other Thread that pick that operation.
By simply move the Event Handler outside the Lock Statement solve my problem.

Related

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

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
}

Ensure events raised in correct order from outside a critical section

Cosider the following sample class:
class MyClass
{
private object syncRoot = new object();
private int value;
public event Action<int> SomethingOccurred;
public void UpdateSomething()
{
int newValue;
lock (syncRoot)
{
// ... Do some stuff that modifies some state of the object.
newValue = ++value;
}
// How to ensure that raising these events are done in the correct order?
SomethingOccurred?.Invoke(newValue);
}
}
In the class above, the events may not occur in the same order that the value was updated apparently, since it's done outside of the lock-statement. The question is, what would be the best way to raise these events outside of the lock statement, but ensuring that they are raised in the correct order (i.e. in this case producing the sequence 1, 2, 3, 4...)?
The best idea I've come up with is to essetially have a ConcurrentQueue or similar to which the values are added, and having a separate thread raise the events based on the values in the queue. But I would prefer to not have a separate thread allocated just for raising these events. Is there a smarter way to accomplish this?
Edit:
My first idea was to have a concurrent queue, and use the following code for raising the event:
int result;
while (m_events.TryDequeue(out result))
SomethingOccurred?.Invoke(result);
The problem with that of course is that it does not guarantee the order either, since multiple threads would dequeue stuff concurrently and the same problem as before persists basically.
I could place another lock around the event-raising, but this would cause the same undesired blocking as raising the events from inside the lock in the first place.
So is there a lock-free way to guarantee only a single thread is dequeueing and raising events in this case? Or is there another way that is better altogether?
Edit 2:
To illustrate a usage, I want to guarantee that the following code would output the sequence 1 through 20 in order:
MyClass myClass = new MyClass();
myClass.SomethingOccurred += (i) =>
{
Thread.Sleep(100); Console.WriteLine(i);
};
Parallel.ForEach(Enumerable.Range(1, 20), i =>
myClass.UpdateSomething());
I don't care if the event handler is called from different threads, but it must not be called concurrently, and it must be called with in the correct order.
The best solution I have so far would be the following which is likely not very efficient use of threading resources:
class MyClass
{
private object syncRoot = new object();
private int value;
private readonly ConcurrentQueue<int> m_events = new ConcurrentQueue<int>();
private object eventRaiserLock = new object();
public event Action<int> SomethingOccurred;
public void UpdateSomething()
{
int newValue;
lock (syncRoot)
{
// ... Do some stuff that modifies some state of the object.
newValue = ++value;
m_events.Enqueue(newValue);
}
// How to ensure that raising these events are done in the correct order?
RaiseEvents();
}
private void RaiseEvents()
{
Task.Run(() =>
{
lock (eventRaiserLock)
{
int result;
while (m_events.TryDequeue(out result))
SomethingOccurred?.Invoke(result);
}
});
}
}
If you need ordering, you need synchronization - it's that simple.
It's not entirely obvious what you're trying to do here - the event you're raising is effectively raised on some random thread. Obviously, that's not going to preserve any ordering, since it's perfectly possible for the events to be running concurrently (since UpdateSomething is called from multiple threads).
A queue is a simple solution, and you don't need to waste any extra threads either - however, you might want to think about the ordering of the UpdateSomething calls anyway - are you sure the items are going to be queued in the proper order in the first place?
Now, ConcurrentQueue is a bit tricky in that it doesn't give you a nice, awaitable interface. One option is to use the Dataflow library - a BufferBlock does pretty much what you want. Otherwise, you can write your own asynchronous concurrent queue - though again, doing this well is quite complicated. You could use something like this as a starting point:
async Task Main()
{
var queue = new AsyncConcurrentQueue<int>();
var task = DequeueAllAsync(queue, i => Console.WriteLine(i));
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Finish();
await task;
}
private async Task DequeueAllAsync<T>(AsyncConcurrentQueue<T> queue, Action<T> action)
{
try
{
while (true)
{
var value = await queue.TakeAsync(CancellationToken.None);
action(value);
}
}
catch (OperationCanceledException) { }
}
public class AsyncConcurrentQueue<T>
{
private readonly ConcurrentQueue<T> _internalQueue;
private readonly SemaphoreSlim _newItem;
private int _isFinished;
public AsyncConcurrentQueue()
{
_internalQueue = new ConcurrentQueue<T>();
_newItem = new SemaphoreSlim(0);
}
public void Enqueue(T value)
{
_internalQueue.Enqueue(value);
_newItem.Release();
}
public void Finish()
{
Interlocked.Exchange(ref _isFinished, 1);
_newItem.Release();
}
public async Task<T> TakeAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
await _newItem.WaitAsync(token);
token.ThrowIfCancellationRequested();
T result;
if (_internalQueue.TryDequeue(out result))
{
return result;
}
Interlocked.MemoryBarrier();
if (_isFinished == 1) throw new OperationCanceledException();
}
throw new OperationCanceledException(token);
}
}
This ensures that you have a queue with a global ordering that you can keep filling, and which is emptied continually whenever there are any items. The removal (and execution of the action) is in order of adding, and it happens on a single worker thread. When there are no items to dequeue, that thread is returned to the thread pool, so you're not wasting a thread blocking.
Again, this is still a relatively naïve solution. You want to add more error handling at the very least (according to your needs - e.g. perhaps the action(value) call should be in a try-catch so that a failed action doesn't stop your dequeue loop?).

Event is not triggered when number of threads is large

I am having trouble with multi-threading and event delegate in C#. If anyone could help me solve this problem, that would be great. The problem is with multiple threads and events. In a single thread or up to 10 threads, custom event is triggered properly and works fine. However, when I increase the number of threads to 15 or 20, event are not triggered at all. Here is sample piece of code:
LegacyMemberStream memberStream=new LegacyMemberStream();
memberStream.OpenStream();
legacyMemberStrm = (LegacyMemberStream)memberStream;
legacyMemberStrm.ThreadErrorOccur += OnParserThreadInterrupt;
Here is code for OnParserThreadInterrupt():
private void OnParserThreadInterrupt(Object Sender, ThreadErrorEventArgs args)
{
// Exception logging is done here
}
And, the part of LegacyMemberStream.OpenStream() method is:
parserThreads[i].OnThreadError = HandleThreadError;
parserThreads[i].StartThread();
This method simply initializes number of threads requested and assigns event for each thread when exception occur and finally starts threads.
And, HandleThreadError method in LegacyMemberStream is :
public void HandleThreadError(Exception exception, string threadName)
{
lock (SyncObject)
{
Console.WriteLine("From parser thread");
for (int i = 0; i < parserThreads.Length; i++)
{
if (parserThreads[i].Name.Equals(threadName))
{
parserThreads[i].StopThread();
break;
}
}
int threadFailureErrorCode = -1111;
OnThreadFailure(new ThreadErrorEventArgs(threadFailureErrorCode, true,exception));
somethingQueue.StopQueuing();
}
}
LegacyMemberStream.OnThreadFailure:
protected virtual void OnThreadFailure(ThreadErrorEventArgs e)
{
lock (_locker)
{
var threaderrorOccur = ThreadErrorOccur;
// Console.WriteLine("Exception occurred");
if (threaderrorOccur != null)
{
ThreadErrorOccur(this, e);
}
}
}
For any number of threads, HandleThreadError() method is called from OnThreadError event.
What I have discovered so far from debugging is that, OnParserThreadInterrupt() method is not being invoked when number of threads are greater than 15 (or sometimes 20). However, for same input and same scenario, OnParserThreadInterrupt() event is triggered when number of threads is lesser. I can't understand why event is not being triggered when number of threads are increased.
Basing on this code that you have shared, the only reason that seems to be possible is that the error happens before you submit the event handler. so just change order of the first lines to be:
LegacyMemberStream memberStream=new LegacyMemberStream();
legacyMemberStrm = (LegacyMemberStream)memberStream;
legacyMemberStrm.ThreadErrorOccur += OnParserThreadInterrupt;
memberStream.OpenStream();
If the context switch was before you got the chance to submit the event handler then this function:
protected virtual void OnThreadFailure(ThreadErrorEventArgs e)
{
lock (_locker)
{
var threaderrorOccur = ThreadErrorOccur;
// Console.WriteLine("Exception occurred");
if (threaderrorOccur != null)
{
ThreadErrorOccur(this, e);
}
}
}
skipped the call to ThreadErrorOccur
because the if statement is false.
Why is that related to number of threads? I think it is matter of probability. Maybe creating many threads consumes enought time so the main thread context switched, then the threads run (also context switched between them), get errors... and all of that happens before the main thread, whci creates them had the chance to do the line that subscribes the ThreadErrorOccur event
Hope it solves your issue.

"If two threads are using Pulse and Wait to interact, this could result in a deadlock."

Basically the load() is for the producer(there's one and only one dispatcher thread that loads the _tickQueue) and the Unload is for the consumer(there's one and only one dedicated thread executing the function). _tickQueue is a regular queue protected by a lock(I'm using itself as the argument to lock()). Surprisingly, it caused deadlock.
public void Load(Tick tick)
{
lock (_tickQueue)
{
while (_tickQueue.Count >= CapSize)
{
Monitor.Wait(_tickQueue);
}
_tickQueue.Enqueue(tick);
if (!_receivedTickCounts.ContainsKey(tick.Underlier))
{
_receivedTickCounts.Add(tick.Underlier, 0);
}
Console.WriteLine("Received {1} ticks for {0}", tick.Underlier, ++_receivedTickCounts[tick.Underlier]);
Monitor.Pulse(_tickQueue);
}
}
private void Unload()
{
while (true)
{
try
{
Tick tick;
lock (_tickQueue)
{
while (_tickQueue.Count == 0)
{
Monitor.Wait(_tickQueue);
}
tick = _tickQueue.Dequeue();
Monitor.Pulse(_tickQueue);
}
Persist(tick);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
The comment in the title was found here:
https://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse%28v=vs.110%29.aspx
My understanding of the "Important" paragraph is: Monitor class not maintaining state (in the way ResetEvent does) implies deadlock. A specific example was given: when two threads interact using Pulse and Wait, if one thread pulses when the other thread is not on the wait queue, then deadlock happens.
Can someone SPECIFICALLY(e.g. give a scenario for deadlock to happen) point out where I did wrong in my program? I don't see any scenario that can possibly lead to deadlock.
Thanks.
===================EDIT====================
Specifically, I'm interested to know why the following coding pattern for monitor suddenly doesn't work - must be related to the monitor implementation in .net?
lock
while(wait condition is met)
{
wait()
}
// critical section: doing work
signal();// or broadcast()
unlock
I suspect you are imposing an un-ending wait upon both methods. You are surrounding your Monitor method calls with While loops continually checking a condition. For certain values of CapSize and _tickQueue.Count, both of your Load() and Unload() methods will be forever waiting. What isn't evident here is the value of CapSize, is it constant, or does it change? Is _tickQueue thread-safe?
What if we reach an error on tick = _tickQueue.Dequeue(); in Unload(), _tickQueue.Count reaches 0, and the Load() method was Waiting()'ing? Load() will be waiting forever.
I would avoid having your consumer method Pulse to notify that Producer method it's ready for more work. Your consumer should only be waiting when there is no more work for it to do (queue is empty). Your Producer would be better suited controlling it's own work schedule, and pulsing the consumer when new work has been queued. Why not put the Producer on a Timer?
In the end, I believe the supplied code simply provides too many points of failure. Could I suggest an alternate implementation? This uses the thread-safe ConcurrentQueue collection and eliminates the discussed issues.
public class StackOverflowMonitorExample
{
ConcurrentQueue<Tick> _tickQueue = new ConcurrentQueue<Tick>();
object locker = new object();
bool stopCondition = false;
public void Load(Tick tick)
{
_tickQueue.Enqueue(tick);
lock (locker)
{
Monitor.Pulse(locker);
}
}
private void Unload()
{
while (!stopCondition)
{
try
{
Tick nextWorkItem = null;
_tickQueue.TryDequeue(out nextWorkItem);
if (nextWorkItem != null)
{
Persist(nextWorkItem);
}
else
{
lock (locker)
{
Monitor.Wait(locker);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
This eliminates the large locking sections, and removes most of the signals between the consumer and producer. The Producer will only ever add new items to the queue, and Pulse() to notify that new work is available. The Consumer will loop and continue to work as long as items remain in the queue, and stop condition has not been met. If queue count reaches 0, then the consumer will wait for new queue entries.

Is it OK to use Monitor.TryEnter in event handler method?

I have EventHandler method which is called pretty often and it's body processing takes some time. Is it OK, to lock operations inside this handler it via Monitor?
The purpose is that meanwhile locker locks the object other events and processing of the object are simply skipped.
public void MyEventHandler(object sender, EventArgs e)
{
if (!Monitor.TryEnter(locker)) return; // skipping meanwhile processing
// do some stuff here
Monitor.Exit(locker)
}
it looks like it would be cleaner/more performant to
(a) prevent the events from being raised
(b) use a condition variable.
Regardless, always put the Monitor.Exit into a finally block
It's not horrible, as long as:
You're doing this on a background thread (or, to the point, you're not doing this on the event handling thread).
You're synchronizing all access to whatever your //do some stuff code needs.
You wrap everything after the TryEnter in a try/finally, like so:
.
public void MyEventHandler(object sender, EventArgs e)
{
if (!Monitor.TryEnter(locker)) return;
try
{
// do some stuff here
}
finally
{
Monitor.Exit(locker);
}
}
It'd be nicer if you could prevent firing the event at all (and thus avoid starting a thread to potentially do nothing -- cause of course you're not doing this time-consuming processing on the event handling thread...)
Alternatively, if you don't really need to lock for the whole duration (that is, if the event handler won't be doing anything that requires synchronization with other code), you could lock just long enough to set a flag, like
private Object condition_lock = new Object();
private bool handlingEvent = false;
public void MyEventHandler(object sender, EventArgs e)
{
lock (condition_lock)
{
if (handlingEvent) return;
handlingEvent = true;
}
try
{
// do some stuff here
}
finally
{
handlingEvent = false;
}
}

Categories

Resources