How does it work?
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.
那么,显然Dispatcher排队实现看起来像一个Win32消息泵,但它不是(尽管它使用相同的User32消息和线程模型)。
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.
链接地址: http://www.djcxy.com/p/10260.html上一篇: 一个类的实例可以在JavaScript中替换它自己吗?
下一篇: 它是如何工作的?