同步上下文SynchronizationContext學習筆記

風靈使發表於2018-06-12

提供在各種同步模型中傳播同步上下文的基本功能。同步上下文的工作就是確保呼叫在正確的執行緒上執行。

同步上下文的基本操作

Current 獲取當前同步上下文

var context = SynchronizationContext.Current;

Send 一個同步訊息排程到一個同步上下文。

SendOrPostCallback callback = o =>
                                 {
                                     //TODO:
                                 };
context.Send(callback,null);

send呼叫後會阻塞直到呼叫完成。
Post 將非同步訊息排程到一個同步上下文。

SendOrPostCallback callback = o =>
                                {
                                      //TODO:
                                };
context.Post(callback,null);

send的呼叫方法一樣,不過Post會啟動一個執行緒來呼叫,不會阻塞當前執行緒。

使用同步上下文來更新UI內容

無論WinFromsWPF都只能用UI執行緒來更新介面的內容

常用的呼叫UI更新方法是Inovke(WinFroms):

private void button_Click(object sender, EventArgs e)
{
       ThreadPool.QueueUserWorkItem(BackgroudRun);
}

private void BackgroudRun2(object state)
{
            this.Invoke(new Action(() =>
                                       {
                                           label1.Text = "Hello Invoke";
                                       }));
}

使用同步上下文也可以實現相同的效果,WinFroms和WPF繼承了SynchronizationContext,使同步上下文能夠在UI執行緒或者Dispatcher執行緒上正確執行

System.Windows.Forms. WindowsFormsSynchronizationContext
System.Windows.Threading. DispatcherSynchronizationContext

呼叫方法如下:

private void button_Click(object sender, EventArgs e)
{
           var context = SynchronizationContext.Current; //獲取同步上下文
           Debug.Assert(context != null);
           ThreadPool.QueueUserWorkItem(BackgroudRun, context); 
}

private void BackgroudRun(object state)
{
    var context = state as SynchronizationContext; //傳入的同步上下文
    Debug.Assert(context != null);
    SendOrPostCallback callback = o =>
                                      {
                                          label1.Text = "Hello SynchronizationContext";
                                      };
    context.Send(callback,null); //呼叫
}

使用.net4.0的Task 可以簡化成

private void button_Click(object sender, EventArgs e)
{
            var  scheduler = TaskScheduler.FromCurrentSynchronizationContext(); // 建立一個SynchronizationContext 關聯的 TaskScheduler
            Task.Factory.StartNew(() => label1.Text = "Hello TaskScheduler", CancellationToken.None,
                                  TaskCreationOptions.None, scheduler);
}

相關文章