Dispatcher的运行机制

归根到底,也还是Windows API,即:

1.通过注册Window Message
2.给当前Window(Win32里的Window)添加Window Procedure来处理注册过的Windows Message,
3. DispatcherFrame的Push方法里则是传统的Translate和DispatchMessage的过程。直到这个Frame不再Continue.
4. 默认的Frame是由Application的RunDispatcher启动起来的,Application是DispatcherObject的子类,带有一个Dispatcher。
5. 由4上溯Application.Run则可以一直上溯到static Main()方法,程序的入口。
一些关键代码:
1. Static Dispatcher() //WindowMessage是整个操作系统级别的,会被所有WPF程序共享
 Dispatcher._msgProcessQueue = UnsafeNativeMethods.RegisterWindowMessage(“DispatcherProcessQueue”);
2. Dispatcher() ctor :
 this._hook = new HwndWrapperHook(this.WndProcHook);

this._window.Value.AddHook(this._hook);

—->

private IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled):
     if (msg == (int)Dispatcher._msgProcessQueue)
{
this.ProcessQueue();
}
—->
ProcessQueue():
 dispatcherOperation.Invoke(); //自带ExecutionContext,顺便说一下,如果是别的线程里BeginInvoke,会ExecutionContext.Capture(),包括synchornizationContext,securityContext在内都抓下来。但是,Invoke机制对SynchronizationContext有特殊处理,这样ExecutionContext.Run()里的SetExecutionContext方法白白flow了SynchronizationContext
// System.Windows.Threading.DispatcherOperation
[SecurityCritical]
private void InvokeImpl()
{
SynchronizationContext current = SynchronizationContext.Current;
bool flag = current != this._dispatcher._dispatcherSynchronizationContext;
try
{
if (flag)
{
SynchronizationContext.SetSynchronizationContext(this._dispatcher._dispatcherSynchronizationContext);
}
this._result = this._dispatcher.WrappedInvoke(this._method, this._args, this._numArgs);
}
3.Dispatcher.PushFrameImpl()
     while (frame.Continue && this.GetMessage(ref mSG, IntPtr.Zero, 0, 0))
{
this.TranslateAndDispatchMessage(ref mSG); //Translate和DispatchMessage的方法就是native的同名方法
}

为什么SynchronizationContext 在WPF中很重要

因为WPF的UI操作必须在UI Thread的Dispatcher上完成。
DispatcherSynchronizationContext 是SynchronizationContext 的一个子类实现,专门为WPF服务的,定义在WindowsBase.dll里的(虽然namespace还是system.Windows.threading).有了它,和别的SynchronizationContext 实现一样,就可以使用它的Post方法。
TaskScheduler抽象类有两个子类,除了默认的新开一个线程的 ThreadPoolTaskScheduler,另一个就是SynchronizationContextTaskScheduler,它就会用SynchronizationContext 的Post方法。这样如果用TaskScheduler.FromCurrentSynchronizationContext(),就会创建一个SynchronizationContextTaskScheduler,就能够保证多线程的队列里的元素执行时都在同一个SynchronizationContext 上执行(除非手动地设置SynchronizationContext ),无论对Winform还是WPF都如此,对取数据等操作如果有SynchronizationContext 上的限制,也都有了保证。对WPF而言,这个DispatcherSynchronizationContext ,是在Dispatcher的构造函数里就和这个Dispatcher联系在一起了。它的Send会立即执行,而它的Post,就会加入Queue,而Queue的处理则是这个Dispatcher的Window Proc(处理Window message loop的自定义方法)里的事情。

一段精巧的代码

internal void EnsureThreadRequested()
{
    int num;
    for (int i = this.numOutstandingThreadRequests; i < ThreadPoolGlobals.processorCount; i = num)
    {
        num = Interlocked.CompareExchange(ref this.numOutstandingThreadRequests, i + 1, i);
        if (num == i)
        {
            ThreadPool.AdjustThreadsInPool(1u);
            return;
        }
    }
}

ThreadPoolWorkQueue类里的,没用Lock就实现了多线程情况下确保+1操作的一次调用。厉害。