Dispatcher - How does it work? - c#

After having read the documentation for the Dispatcher class, I realize that it can be used for non-UI queueing of actions too.
So how does the Dispatcher class actually works? I'm aware of that, it's main job is to queue actions to a specific thread - but how does it "send" those actions to the thread? And how do the thread "get" these actions?
My best guess is that there's some kind of "thread queue" for each thread, but then again I've got no idea.

It is not a trivial task to get one thread to initiate execution of code onto another thread. The crux of the problem is that you cannot simply tell any thread to start executing a method after that thread has already started. The target thread has to be specifically setup to receive these kind of requests ahead of time.
The usual pattern used is the producer-consumer. The target thread will spin around an infinite loop waiting for messages to appear in a blocking queue. The queue is designed to block until an item appears in the queue thus preventing the target thread from consuming CPU time unnecessarily. Here is a really simple way to get a thread to accept the injection of a delegate for execution.
public class Example
{
private BlockingCollection<Action> queue = new BlockingCollection<Action>();
public Example()
{
new Thread(
() =>
{
while (true)
{
Action action = queue.Take();
action();
}
}).Start();
}
public void ExecuteAsync(Action action)
{
queue.Add(action);
}
}
Now, in the case of a UI thread it already has a message loop running so the Dispatcher class can simply post a special message to the message queue containing the delegate to be executed. In the middle of processing all of the paint, button clicks, etc. this special message will be picked up by the UI thread as well and it will begin executing the delegate.
So how does the Dispatcher class actually works? I'm aware of that,
it's main job is to queue actions to a specific thread - but how does
it "send" those actions to the thread?
By queuing a delegate into a queue that the target thread monitors.
And how do the thread "get" these actions?
By running an infinite loop that monitors the queue. The queue is usually a special type called a blocking queue which blocks the consuming thread if the queue is empty.
My best guess is that there's some kind of "thread queue" for each
thread, but then again I've got no idea.
Pretty close. Except that threads do not actually have a built in queue for this purpose. It has to be manually setup. That is why only threads that are specifically designed can accept delegate injections. UI threads are setup this way because Application.Run creates the message loop. In my example you will see that I had to use BlockingCollection and an infinite loop to get it to work on a worker thread.

Well, apparently the Dispatcher queuing implementation looks like a Win32 message pump but it's not (although it uses the same User32 messages and threading model).

Very interesting question, But you don't need a Window to have a message queue, these are separate concepts, you can create a message queue on any thread just by calling PeekMessage.
For more information take a look at here
but of course it doesn't mean that a Dispatcher without a window is of any use. I can assume that the designers were thinking about an independent Dispatcher object in order to let it handle as many window as the application have.

Related

Why does Control.Invoke() calls PostMessage() instead of SendMessage()?

Control.Invoke() calls PostMessage() and then waits until the UI thread finishes processing the message. So why it does not calls SendMessage() instead (which by default waits until the UI thread finishes processing the message).
Control.Invoke() is a dangerous method, many .NET programmers have deadlocked their program with it. It should be very strongly avoided because of this. Simple everyday operations like closing a window become perilous. You'll want to wait until a worker thread cannot invoke anymore since nothing good happens when the thread keeps running but the UI is gone. So you signal the thread with, say, AutoResetEvent and wait for it to complete.
Such a wait is very likely to deadlock your program when the thread is calling Invoke() at just the wrong time. The thread cannot complete because it is stuck in the Invoke() call, the UI thread cannot service it since it is stuck in the wait. A "deadly embrace", neither thread can make progress and your program will hang. Quite hard to debug since it is not predictable and doesn't happen often enough, only goes wrong when the thread calls Invoke at exactly the same time.
Breaking that deadlock requires knowing that an Invoke() call is in progress so it can be cancelled. It is not knowable when you use SendMessage(). The lock on which it blocks is hidden in the OS. I've recently posted an answer about the problems with SendMessage, everything you read there applies here as well.
So Microsoft did not implement it that way and they use PostMessage. They add an entry to the invoke queue, call PostMessage to wake up the UI thread so it goes looking through that queue. And specific to Invoke over BeginInvoke, they block on a ManualResetEvent in the queue entry, signaled when the UI thread completed the call to the delegate target.
Now they can do something to avoid the deadlock, when a window closes it looks through the invoke queue and cancels any that had that window as the invoke target. Or in other words, the lock that's invisible when you use SendMessage and causes deadlock now becomes visible and can be released to break the deadlock.

Is rampant use of Control.Invoke and Control.InvokeRequired healthy?

I am writing a client server application that works like this:
Form1 loads and creates ServerHost. ServerHost is started to listen for TcpClient connections, on connected and accepted, ServerHost spawns a thread by way of ThreadPool.QueueUserWorkItem(DoWork, client);
Within the DoWork() thread, I want to update Winform Controls on Form1.
This is achieved by having events in ServerHost such as ServerHost.SomethingHappened. When something happened in DoWork(), it raises the event and the Form1.Handler is called to update the winforms control.
This set up gives me cross-thread operation error.
Is use of Control.Invoke and Control.InvokeRequired healthy? I am not good at threads, and MSDN is saying to use BackgroundWorker, but I can't see how to do it here. Any advice to change the structure to avoid using Invoke in this set up?
Control.Invoke is highly questionable, and Control.InvokeRequired is downright toxic.
If at all possible, use the new async/await support, and you won't need to explicitly marshal back to the UI thread. Also, use Task.Run instead of ThreadPool.QueueUserWorkItem for background work.
The problem with Control.Invoke is that it ties your library to a specific UI (WinForms). Capturing a SynchronizationContext is a step above that, and implicitly capturing the SynchronizationContext by using await is even better.
You have to invoke the code that updates the user interface on the UI thread.
In general there are several options to do that:
calling Invoke on a Control
using a BackgroundWorker that has been started on the UI thread
calling Post on the SynchronizationContext of the UI thread
using Task.ContinueWith with the TaskScheduler of the UI thread
using asynchronous calls with async/await
In my opinion last method is by far the easiest for the developer, but it is only available with C# 5 and .NET 4.5 or .NET 4.0 with the Microsoft.Bcl.Async package. Tasks are nearly as easy to use but both of these methods would require you to change your code. They won't work to simply invoke a method on the UI thread from a thread pool thread.
The BackgroundWorker is usually used to schedule an action that takes quite some time. Its ReportProgress method raises the ProgressChanged event on the thread that called the RunWorkerAsync method. As such it is also not a good solution to your problem.
SynchronizationContext.Post and Control.Invoke work similarly, but Control.Invoke doesn't require you to capture the UI context, so it's easier to use.
To summarize it you should use Control.Invoke unless you want to change your code to make use of async/await.
It's fine as long as the UI thread isn't overburdened by those invokes. It does introduce some latency to the communication, which usually isn't an issue, however, it can become more of a problem if you're doing a lot of Invokes, or if the UI thread is doing a lot of work (eg. rendering complex graphs or something like that). Invoke is a synchronous method - it will not return until the invoked command is actually processed, and returns its return value.
As long as you're not tied up by these issues, all is well. Profiling and performance testing is critical to allocate your resources correctly, guessing is usually a huge waste of time and resources.
If you don't need the resulting value (or at least not synchronously) and you're starting to get into performance trouble, have a look at BeginInvoke, which handles the invoking asynchronously. This means your networking thread doesn't have to wait for the UI thread to work. This is quite critical in high performance servers with thousands of connections. They simply can't afford to wait while the UI does its thing.
However, do note, that having a server socket running on a different thread is not a good solution for larger servers, and in fact, it's no longer the easiest solution either. .NET now has great support for asynchronous calls and callbacks, making implementations of asynchronous processing a breeze. In your typical Winforms application, it means that I/O blocking applications can work without having constantly running and polling threads. For example, waiting for a new connection can be as simple as:
var connection = await listener.AcceptTcpClientAsync();
That's it. Automagically, all the callbacks will be processed at the right time, without blocking the processing, all of your own code always running on the main UI thread. In other words, you can easily do this:
while (!aborted)
{
var connection = await listener.AcceptTcpClientAsync();
tbxLog.Text += "New connection!\r\n";
}
While this seems like an infinite loop blocking the UI thread indefinitely, the reality is that when the application gets to the await keyword, it will register an asynchronous callback and returns. Only when the asynchronous callback is actually invoked (by IOCP in this case) is the code resumed (on the UI thread), and tbxLog has the text appended, followed by waiting for another connection.
I've never had problems doing it this way. No matter how you set it up, updating your controls has to be done on the thread they were created on. If you use a BackgroundWorker or some other async construct, somewhere an invoke is going to be called. I typically create a method on the form like:
delegate void TextSetter(string text);
internal void SetText(string text)
{
//call on main thread if necessary
if (InvokeRequired)
{
this.Invoke((TextSetter)SetText, text);
return;
}
//set the text on your label or whatever
this.StatusLabel.Text = text;
}
I've used that method in a number of applications and it's never been a problem, even updating many times per second.
As far as I'm aware, the only way to get around calling an invoke is to have your main thread constantly poll for updates, which is generally accepted as a really bad way to do things.
A really obvious simplification is to abstract away the InvokeRequired/Invoke into an extension method for a Control.
public static class FormExt {
public static void Execute(this Control c, Action a) {
if (c.InvokeRequired) {
c.Invoke(a);
} else {
a();
}
}
}
Now you just wrap up normal form updates into a lambda and execute them.
form1.Execute(() => form1.Text = "Hello world");

Sending Events to a specific Thread

I have a situation in which I want a thread to process some sequential logic. This thread would need to interact with the main thread on occasion in order to update user input. But it should continue running otherwise without bothering the main thread. I am hopping to do this in an event-driven manner, so that the main thread doesn't have to pole the other thread for interrupts. What is the best way to do this? Is there an event-driven technique to communicating between threads much like there is in MFC?
I am using Visual Studio 2008 and (obviously) the .Net 3.5 framework.
Use the BackgroundWorker component.
Here you can find the best and complete tutorial about threading in C#, with code samples and examples.
AutoResetEvent and ManualResetEvent might be what you are after. Basically your main thread would wait using the various Wait methods of these classes until you signal from your other thread using the Set method. Then your wating thread will resume and continue with whatever comes afer Wait.
This is as good as it gets for an event-style. You have to wait and listen to receive an react on an event. How else are you supposed to stop your thread work in case you get an event gracefully? This is not possible with threads in general in any language.
Your only other possibility is frequent interrupting and polling.
Have a look at .Net Reactive Extensions IObservable and in particular the SubscribeOn and ObserveOn extension methods.
ObserveOn is where the work is done ( your background thread ), SubscribeOn is where the notifications go ( your UI thread ).
If you are using the BackgroundWorker you can raise a Progress event.
Here's an example on how to update a progress bar.
Ah ha! there is an event-driven way to do it. I borrowed the Dispatcher from WPF. I just give the spinning thread access to the main thread's CurrentDispatcher I let the thread spin and when it needs attention it invokes a delegate on the Dispatcher and sleeps waiting for the main thread to interrupt it. I know I could use Invoke instead of BeginInvoke, but I needed to use the interrupt because the method that restarts the worker thread is not a synchronous part of the dispatched delegates stack.
For better or worse, here is my code:
private void Run()
{
while (true)
{
...
// Need attention from the main thread
// "_main" is the main thread's Dispatcher instance.
_main.BeginInvoke(new MyEventHandler(OnNeedsAttention), this, new MyEventArgs(...));
try
{
Thread.Sleep(Timeout.Infinite);
}
catch (ThreadInterruptedException) { }
}
}

Thread, abort and wait

I am aborting a thread (will be threads soon enough) and the problem is i need to stall until all threads have been aborted.
After doing the Thread.Abort(); I thought of using the Thread.Join() to wait until its been fully aborted. However that doesnt work. It just waits forever. How can i abort each thread and wait until its done before continuing?
Additional information: If your curious why - in this case I am closing a window, I pass a delegate func into the thread which it calls when its done (or aborted). If I dont stall then the window will close and the function will call invalid handles/objs. I can easily use the same method, stick a flag in and loop & sleep until all flags are set but that doesnt feel right.
I've learnt from many years experience with threads that there are a couple of rules that, if followed, make life a lot easier.
The one pertinent to this question is:
let threads control their own resources, including their lifetime.
I wouldn't abort a thread, I'd simply set up a communications method between the threads creator and the thread itself to signal the thread to terminate, and then let the thread itself shut down.
This method can often be as simple as a write-by-creator/read-by-thread flag which controls the threads main loop. If the thread has long running tasks while in the loop, you should also check periodically.
Then the creator thread should just join until the thread exits. Properly designed, you can set an upper limit to the time this will take.
Use a synchronisation object such as an Event. For example, each background thread has an Event associated with it. When the thread is terminating, it signals the Event. The main thread does a WaitHandle.WaitAll on the set of Events, and proceeds only when all Events are signalled.
Be warned that if there is a chance that the background threads will take a long time to terminate, blocking the main thread while waiting for them would create a bad user experience. So if this is the case, you may want to hide the window before blocking. Also, you'll want to test what the impact of this is on your callback delegate -- if the UI thread is blocked in a wait, will it be able to handle your delegate?
Might not a better design be not to call the delegate if the thread is being killed due to the window closing? Just have the main thread tell the background threads why they are terminating and have them skip the callback if the reason is "window closing." (This assumes that you are communicating with the threads, as Pax rightly recommends, rather than just calling Abort.)

Winforms should I multi thread or use event timer?

I currently have a thread that listens for data from the network and then runs rules on it. I then want to pass the data to the GUI. I am worried about having a deadlock in the GUI. I cant figure out were to put the mutexes on the GUI side. I am also using c# and dotnet 3.5.
What I have come up with is
1) Using a timer to create an event and dump the thread. Worried about performance.
2) Use an intermediary event to copy the data to GUI.
3) Dig in and figure out thread safe way of using GUI.
What do you think is best way to proceed?
Edit: Here is the solution I am using. I pass in the changed element and then protect the big object with a mutex. I use helper function to switch threads using InvokeRequired then BeginInvoke with a delegate. Pulled from reading the answers and then following links until reaching Threading in Windows Forms by Jon Skeet.
delegate void UInt32ParameterDelegate(UInt32 n);
public void UpdateLocation(UInt32 n)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new UInt32ParameterDelegate(UpdateLocation), new object[] { n });
return;
}
// Must be on the UI thread if we've got this far
this.engine.location.UpdateBusy.WaitOne();
// do the work in here
this.engine.location.UpdateBusy.ReleaseMutex();
}
Synchronization is very easy in Windows Forms. You can call Control.Invoke() in the background thread. The thread will stall until the delegate has finished running on the UI thread. No sync required at all.
If stalling the thread is a problem, use Control.BeginInvoke(). You'll have to protect the object(s) you pass to the delegate with a lock if the thread might alter them while it continues running. That's rarely the case in a producer-consumer scenario, the thread can simply create new objects.
Do make sure that you don't Invoke() too often. Do it more frequently than about 1000 times per second and the UI thread will stop pumping Windows messages, being bogged down by handling the invoke requests. Since it is human eyes you're trying to please, invoking more than about 25 times per second is just wasted effort. Pool intermediate results in a collection object.
I hope I understand your problem correctly.
After the background thread reads the data and does whatever it wants, it should use Invoke to call a method on the GUI thread. That method would update anything that should be updated in the GUI.
Never read from the network on the GUI thread. It's only a matter of time before your application runs during a network outage and your GUI hangs as a result. This will really frustrate your users.
In your situation I think the best approach is to have a background thread complete the read operation. Then take the resulting data and move it back to the GUI thread via a SynchronizationContext Post or Send method.
you should just pass an event from your network thread to your UI thread.
then cross threads using begininvoke so you don't get a cross thread exception.
Need help getting info across a UI thread and another thread in C#
You could use a backgroundworker that will process the datareading in a background thread and when it's done you can end the backgroundworker triggering it's RunWorkerCompletedEventHandler. In the RunWorkerCompletedEventHandler you can update your GUI thread with the result.
Isn't easier to just throw a delegate who raise an event that inform the form to refresh itself?

Categories