Just to put the questions upfront (please no comments about the bad architecture or how to revise - suppose this is what it is):
How does the "lock" statement apply when using Invoke/BeginInvoke
Could the following code result in a deadlock?
Suppose I have the following BindingList that I need to update on the GUI Thread:
var AllItems = new BindingList<Item>();
I want to make sure that all updates to it are synchronized.
Suppose I have the following subroutine to do some calculations and then insert a new entry into the BindingList:
private void MyFunc() {
lock(locker) {
... //do some calculations with AllItems
AddToArray(new Item(pos.ItemNo));
... //update some other structures with the contents of AllItems
}
}
And AddToArray looks like:
private void AddToArray (Item pitem)
{
DoInGuiThread(() =>
{
lock (locker)
{
AllItems.Add(pitem);
}
});
}
And DoInGuiThread looks like:
private void DoInGuiThread(Action action) {
if(InvokeRequired) {
BeginInvoke(action);
} else {
action.Invoke();
}
}
The lock is held till you leave the lock block, your current code does not cause a deadlock however it also does not work correctly either.
Here is the sequence of events:
On a background thread you call MyFunc.
A lock is taken for the background thread for the object locker
The background thread will "do some calculations with AllItems"
The background thread calls AddToArray from MyFunc passing in pitem
The background thread calls DoInGuiThread from AddToArray
The background thread calls BeginInvoke from DoInGuiThread, the thread does not block, I will use A to signify the background thread
and B to signify the UI thread, both of these are happening at the
same time.
A) BeginInvoke returns from it's call because it is non blocking.
B) The UI hits lock (locker) and blocks because the lock is held by
the background thread.
A) DoInGuiThread returns.
B) The UI is still locked up, waiting for the background thread to release the lock.
A) AddToArray returns.
B) The UI is still locked up, waiting for the background thread to release the lock.
A) The background thread will "update some other structures with the contents of AllItems" (note, pitem has not yet been added to
AllItems)
B) The UI is still locked up, waiting for the background thread to release the lock.
A) The background thread releases the lock for the object locker
B) The UI thread takes the lock for the object locker
A) MyFunc returns.
B) pitem is added to AllItems
A) Whoever called MyFunc continues to run code
B) The UI thread releases the lock for the object locker
A) Whoever called MyFunc continues to run code
B) The UI thread returns to the message pump to process new messages and no longer appears to be "locked up" by the user.
Do you see the issue? AddToArray returns but the object is not added to the array until the end of MyFunc so your code after AddToArray will not have the item in the array.
The "usual" way to solve this is you use Invoke instead of BeginInvoke however that causes a deadlock to happen. This is the sequence of events, Steps up to 6 are the same and will be skipped.
The background thread calls Invoke from DoInGuiThread
A) Invoke waits for B to return to the message pump.
B) The UI hits lock (locker) and blocks because the lock is held by the
background thread.
A) Invoke waits for B to return to the message pump.
B) The UI is still locked up, waiting for the background thread to release
the lock.
A) Invoke waits for B to return to the message pump.
B) The UI is still locked up, waiting for the background thread to release
the lock.
A) Invoke waits for B to return to the message pump.
B) The UI is still locked up, waiting for the background thread to
release the lock.
(This repeats forever)
There's two different ways this is likely to go down.
You're doing all of this on the GUI thread
You're starting this call chain on some other thread
Let's deal with the first first.
In this case there won't be a problem. You take the lock in MyFunc, you call AddToArray which calls DoInGuiThread passing in a delegate. DoInGuiThread will notice that invoking is not required and call the delegate. The delegate, executing on the same thread that now holds the lock, is allowed to enter the lock again, before calling AllItems.Add.
So no problem here.
Now, the second case, you start this call chain on some other thread.
MyFunc starts by taking the lock, call AddToArray which calls DoInGuiThread passing the delegate. Since DoInGuiThread now detects that it needs to invoke it calls BeginInvoke passing in the delegate.
This delegate is queued on the GUI thread by ways of a message. Here's where things again diverge. Let's say the GUI thread is currently busy, so it won't be able to process messages for a short while (which in this context means "enough to let the rest of this explanation unfold").
DoInGuiThread, having done its job, returns. The message is not yet processed. DoInGuiThread returned back to AddToArray which now returns back to MyFunc which releases the lock.
When the message is finally processed, nobody owns the lock, so the delegate being called is allowed to enter the lock.
Now, if the message ended up being processed before the other thread managed to return all the way out of the lock, the delegate now executing on the GUI thread would simply have to wait.
In other words, the GUI thread would block inside the delegate, waiting for the lock to be released so it could be entered by the code in the delegate.
Related
This question already has an answer here:
Best Way to send message to thread
(1 answer)
Closed 9 years ago.
I have two non UI Threads.
Thread A
Thread B
Thread A raise an event and Thread B listen to this event. When the Thread B Event Listener is executed, it got executed on Thread A (I think, because Thread A raises the event).
What I'd like to do is, be able to raise an event on Thread A and if Thread B is listening, the Listener should get executed on Thread B.
Something like this:
private void SomeMethodOnThreadA()
{
synchronizationContextOfThreadB.Send(new SendOrPostCallback(o =>
{
EventXy(this, new EventArgs());
}), null);
}
But this is not working since I’m my threads are non UI threads.
Thread B isn't listening to the event. It may have been the thread that added the event handler, but that thread isn't what's listening.
You can't just go at any time and tell a currently running thread to go and execute some other method instead of what it's doing. When you start a new thread you give it a place to start, and it just executes code there until it's done, and that's all.
When you run code on the UI thread you can do it because the UI thread has a message loop. It has a queue of delegates, and the code that the thread is running looks something like this:
while(!applicationStopped)
{
Action nextAction = queue.Dequeue();
nextAction();
}
While there is a bit more to it (error handling, for example) that's the general idea. To "run code in the UI thread" you just add a delegate to the queue, and it will eventually be run in the UI thread.
You'll need some similar mechanism if you want to run code in your thread B. You'll need to have some sort of delegate, queue, or other medium of providing a delegate that it should execute, and that thread needs to be checking that location for delegates that it's supposed to run. In the general case, this is often not feasible, unless this other thread is similar to a UI thread in that it does nothing but execute delegates it's given from other locations.
A Thread isn't responsible for receiving an event. It's the thread that invokes the eventhandlers.
You can go two ways:
1) Using something like a messaging queue. Thread A queue's an object to a queue (dataobject/action) and thread B tries to process items from the queue. (Fire and Forget) So Thread B must monitor the queue.
2) You could create a dispatcher on that thread and Invoke an Action on it. (I made a simple DispatcherThread class here: http://csharp.vanlangen.biz/threading/dispatcherthread/) it will create a thread with a Dispatcher so you can invoke actions on it.
According to MSDN, Monitor.Wait():
Releases the lock on an object and blocks the current thread until it
reacquires the lock.
However, everything I have read about Wait() and Pulse() seems to indicate that simply releasing the lock on another thread is not enough. I need to call Pulse() first to wake up the waiting thread.
My question is why? Threads waiting for the lock on a Monitor.Enter() just get it when it's released. There is no need to "wake them up". It seems to defeat the usefulness of Wait().
eg.
static object _lock = new Object();
static void Main()
{
new Thread(Count).Start();
Sleep(10);
lock (_lock)
{
Console.WriteLine("Main thread grabbed lock");
Monitor.Pulse(_lock) //Why is this required when we're about to release the lock anyway?
}
}
static void Count()
{
lock (_lock)
{
int count = 0;
while(true)
{
Writeline("Count: " + count++);
//give other threads a chance every 10th iteration
if (count % 10 == 0)
Monitor.Wait(_lock);
}
}
}
If I use Exit() and Enter() instead of Wait() I can do:
static object _lock = new Object();
static void Main()
{
new Thread(Count).Start();
Sleep(10);
lock (_lock) Console.WriteLine("Main thread grabbed lock");
}
static void Count()
{
lock (_lock)
{
int count = 0;
while(true)
{
Writeline("Count: " + count++);
//give other threads a chance every 10th iteration
if (count % 10 == 0)
{
Monitor.Exit(_lock);
Monitor.Enter(_lock);
}
}
}
}
You use Enter / Exit to acquire exclusive access to a lock.
You use Wait / Pulse to allow co-operative notification: I want to wait for something to occur, so I enter the lock and call Wait; the notifying code will enter the lock and call Pulse.
The two schemes are related, but they're not trying to accomplish the same thing.
Consider how you'd implement a producer/consumer queue where the consumer can say "Wake me up when you've got an item for me to consume" without something like this.
I myself had this same doubt, and despite some interesting answers (some of them present here), I still kept searching for a more convincing answer.
I think an interesting and simple thought on this matter would be: I can call Monitor.Wait(lockObj) at a particular moment in which no other thread is waiting to acquire a lock on the lockObj object. I just want to wait for something to happen (some object's state to change, for instance), which is something I know that will happen eventually, on some other thread. As soon as this condition is achieved, I want to be able to reacquire the lock as soon as the other thread releases its lock.
By the definition of the Monitor.Wait method, it releases the lock and tries to acquire it again. If it didn't wait for the Monitor.Pulse method to be called before trying to acquire the lock again, it would simply release the lock and immediately acquire it again (depending on your code, possibly in loop).
That is, I think it's interesting trying to understand the need of the Monitor.Pulse method by looking at its usefulness in the functioning of the Monitor.Wait method.
Think like this: "I don't want to release this lock and immediately try to acquire it again, because I DON'T WANT to be ME the next thread to acquire this lock. And I also don't want to stay in a loop containing a call to Thread.Sleep checking some flag or something in order to know when the condition I'm waiting for has been achieved so that I can try to reacquire the lock. I just want to 'hibernate' and be awaken automatically, as soon as someone tells me the condition I'm waiting for has been achieved.".
Read the Remarks section of the linked MSDN page:
When a thread calls Wait, it releases the lock on the object and enters the object's waiting queue. The next thread in the object's ready queue (if there is one) acquires the lock and has exclusive use of the object. All threads that call Wait remain in the waiting queue until they receive a signal from Pulse or PulseAll, sent by the owner of the lock. If Pulse is sent, only the thread at the head of the waiting queue is affected. If PulseAll is sent, all threads that are waiting for the object are affected. When the signal is received, one or more threads leave the waiting queue and enter the ready queue. A thread in the ready queue is permitted to reacquire the lock.
This method returns when the calling thread reacquires the lock on the object. Note that this method blocks indefinitely if the holder of the lock does not call Pulse or PulseAll.
So, basically, when you call Monitor.Wait, your thread is in the waiting queue. For it to re-acquire the lock, it needs to be in the ready queue. Monitor.Pulse moves the first thread in the waiting queue to the ready queue and thus allows for it to re-acquire the lock.
i have main thread (MainThread) on which I create new thred (lets call it NewThread). In NewThread I call a method that want to invoke some method for MainThread.
The problem is that when I call NewThread.Join() from MainThread, Invoke method from NewThread cant be accomplished/terminate (and whole application freeze for ever...) because MainThread is waiting for NewThread to terminate...
sth like vicious circle... Any ideas how to solve it? I need to have possibility to terminate/abort NewThread from MainThread and be shure NewThread no longer exist.
I hope I was specific enough.
Main thread:
void method()
{
if(currentthread!=null)
{
currentthread.Join();
currentthread=null;
}
sth...
Backgroundworker worker = new Backgroundworker();
worker.DoWork += delegate (...)
{
currentthread=Thread.CurrentThread;
Func();
}
....
}
NewThread:
delegate void FuncDel();
void Func()
{
if(MainThread.InvokeRequired)
{
FuncDel funcD = new FuncDel();
MainThread.InvokeRequired(funcD);
return;
}
....
}
Well, the obvious answer is that your main thread should never Join() your worker thread if there's a chance the worker thread is going to try to Invoke() something on the main thread.
If you are only using Join() to wait for a shutdown on the main thread, you should first do something like a Thread.Abort(), or better yet, use a thread synchronization object like a Mutex or a shared variable, to indicate to the worker thread that it needs to abort. Once you have signaled the worker thread to abort, then allow your main thread to Join() it; your worker thread should always check to see if it has been aborted before trying to Invoke a method on the main thread.
If you're using Join() for some other reason, you should again look into the thread synchronization objects like a Mutex. These allow your threads to wait for each other to send them signals -- your worker thread could "wake up" your main thread before it needs to Invoke(), to ensure your main thread is getting CPU time to do it's work.
That's what Thread.Join does, it blocks your calling thread until the Joined thread terminates. I guess I don't know why you're using join if you simply want to Invoke on another thread. As was stated before, code would help clarify the situation.
You can poll ThreadState in order to check the state of your threads vs using a Join if your implementation won't allow for you to block your main thread.
It sounds like you almost want the cancellation pattern. Try this TPL option:
CancellationTokenSource cts = new CancellationTokenSource();
Task.Factory.StartNew(() =>
{
if(cts.Token.IsCancellationRequested)
return;
// Do Stuff
});
You can basically fire off a task for the operation you want to do, and if you need to cancel it, you can simply call
cts.Cancel();
Your example is pretty convoluted; having a thread spun off to invoke some method has nothing to do with the original thread.
Consider the following test snippet:
// act
AutoResetEvent workDoneEvent = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(delegate
{
ProcessAndSignal(processor, workDoneEvent);
}, null);
// let worker thread have a go
workDoneEvent.WaitOne();
blockingFetcher.WaitForNextMessage = false;
// assert
Assert.That(processor.StopCause, Is.Null);
}
private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent)
{
workDoneEvent.Set();
// this invocation will block until the WaitForNextMessageFlag is set
processor.ProcessMessages();
}
Ideal scenario:
ProcessAndSignalMethod is queued on the thread pool but does not start to execute.
The main thread blocks (autoResetEvent.WaitOne())
A worker thread starts to execute the "ProcessAndSignal" method
The worker threads has enough time to signal the flag and start execution of the ProcessMessages method
The main thread is spawned back into life and sets the property which will cause the ProcessAndSignal method to complete gracefully
Can the following scenario occur?
1) ProcessAndSignal() will start to execute before the main thread sets the AutoResetEvent to WaitOne() which will cause a deadlock (the processor.ProcessMessages() will go into an infinitive loop)
Yes, the scenario can occur. Yes it can deadlock if you don't declare the bool variable as volatile. Just don't use a bool, use an event like you did.
The logic looks weird, it smells like you are trying to let the main thread wait for the processing to be completed. The workDoneEvent doesn't actually signal that the work was done. Right now the main thread will check the assert before the worker is done, that can't be good. If the intention was that it signals that the worker is done then ProcessAndSignal should be the one calling Set(), at the end of the method. And the main thread should call WaitOne().
If this is at all accurate then you just should not use QUWI, just call ProcessAndSignal directly without using a thread. Far more efficient, zero odds for threading problems.
I am having a problem, for which I am not able to find a solution. The problem is as follows:
In the main thread (the default thread), I am starting a thread and then immediately in the main thread, I wait for the thread's exit by calling Thread.Join on the spawned thread. When I do that if the spawned thread tries to callback in the main thread's context by calling Dispatcher.Invoke, it hangs. Any ideas how I can allow the callback?
The callback has the logic to signal the thread to exit. Without executing the callback, the thread will never exit, and so the main thread is also stuck.
What's the point of starting a new thread if you just wait for it to complete ? Just do the work on the main thread...
I'm not exactly sure what you are asking but you may try BeginInvoke instead of Invoke
If you're only going to be waiting on the thread to terminate, you could simply have a polling loop, like this:
// var otherThread = ...;
volatile bool terminate = false;
while (!terminate)
{
Thread.Sleep(100);
}
otherThread.Join();
Then, leave it up to the callbacks to set the terminate flag to true once you're ready to join.
I had a similar problem which I finally solved in this way:
do{
// Force the dispatcher to run the queued operations
Dispatcher.CurrentDispatcher.Invoke(delegate { }, DispatcherPriority.ContextIdle);
}while(!otherthread.Join(1));
This produces a Join that doesn't block because of GUI-operations on the other thread.
The main trick here is the blocking Invoke with an empty delegate (no-operation), but with a priority setting that is less than all other items in the queue. That forces the dispatcher to work through the entire queue. (The default priority is DispatcherPriority.Normal = 9, so my DispatcherPriority.ContextIdle = 3 is well under.)
The Join() call uses a 1 ms time out, and re-empties the dispatcher queue as long as the join isn't successful.