Parallel dev: .NET SynchronizationContext 二三事

来源:互联网 发布:软件开发相关书籍 编辑:程序博客网 时间:2024/06/06 04:39

原文地址:https://msdn.microsoft.com/magazine/gg598924.aspx

首先, 要了解到底什么是抽象上下文. 

.NET 实现的抽象上下文可以给我们一个大概的印象. 在 mscorlib.dll 库中, System.Threading.SynchronizationContext 类是 .NET 提供的实现.

它提供了一个用于在不同的同步模式之间传递抽象上下文的功能. 这个类有个无参构造函数, 静态的属性表示当前的线程的同步上下文 Ccurrent. 有个 CreateCopy 方法. 

IsWaitNotificationRequired() 方法确定当前对象是否需要等待线程通知. 两个虚方法 OperationCompleted OperationStarted 用来响应操作完成的动作. 

Post 和 Send 方法用来给别的上下文传递异步信息. 静态方法 SetSynchronizationContext 用来设置当前的同步上下文对象.  Wait 方法等待操作句柄收到通知. 

今天开发遇到一个问题,stack overflow上有很简单的解决办法,但是我同事发现用那个解决办法有可能导致ui操作无法在ui线程上执行。

具体问题如下:

1. TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
//TaskScheduler scheduler = TaskScheduler.Default;
2. SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
3. Task.Factory.StartNew(action).ContinueWith(result, scheduler);
scheduler是干嘛的? 可以不要吗
FromCurrentSynchronizationContext报错,察看当前context: System.Threading.SynchronizationContext.current 是第三方的Context
导致报错,can't be used as a scheduler


MSDN 上有篇文章

Parallel Computing - It's All About the SynchronizationContext

恰好是关于这个主题的,摘抄重点如下:

ISynchronizeInvoke --> SynchronizationContext
ISynchronizeInvoke: 1. determining if synchronization was necessary
 2. queue uow from one thread to another
SynchonizationContext: 1. queue uow to a context
 2. no way to determining if synchronization is necessary
 3. keeps count of outstanding asynchronous operations
 
Thread: 1. have a "current" context
2. its context is not necessarily unique
3. it's possible to change thrad's current context

Single UI threads: all delegates queued to them are executed one at a time by a specific UI thread in the order they were queued.
WindowsFormsSynchronizationContext 
DispatcherSynchronizationContext 


Default(ThreadPool)SynchronizationContext: if current context is null, then it has a default context. It's also implicitly applied to child threads 
unless the child thread sets its own context.Thus, UI applications usually have two synchronization contexts: the UI SynchronizationContext covering the UI thread, and the default SynchronizationContext covering the ThreadPool threads
https://i-msdn.sec.s-msft.com/dynimg/IC468121.jpg


https://i-msdn.sec.s-msft.com/dynimg/IC468122.jpg
BackgroundWorkers do not have to run in UI Context!!!


SynchronizationContext provides a means for writing components that may work within many different frameworks. BackgroundWorker and WebClient are two examples that are equally at home in Windows Forms, WPF, Silverlight, console and ASP.NET apps.


Not all SynchronizationContext guarantee the order of delegate execution or synchronization of delegates. UI-based context do satisfy these conditions.
it’s best to not assume that any context instance will run on any specific thread


event-based asynchronous pattern VS task-based asynchronous pattern


when re-entrancy is desired, such as a client invoking a server method that invokes a client callback.


Task Parallel Library: TaskScheduler.FromCurrentSynchronizationContext and CancellationToken.Register
default TaskScheduler works like default context.
Figure 5 Progress Reporting with UI Updates


private void button1_Click(object sender, EventArgs e)
{
  // This TaskScheduler captures SynchronizationContext.Current.
  TaskScheduler taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
  // Start a new task (this uses the default TaskScheduler, 
  // so it will run on a ThreadPool thread).
  Task.Factory.StartNew(() =>
  {
    // We are running on a ThreadPool thread here.

  
    ; // Do some work.

  // Report progress to the UI.
    Task reportProgressTask = Task.Factory.StartNew(() =>
      {
        // We are running on the UI thread here.
        ; // Update the UI with our progress.
      },
      CancellationToken.None,
      TaskCreationOptions.None,
      taskScheduler);
    reportProgressTask.Wait();
  
    ; // Do more work.
  });
}


Figure 4 Summary ofSynchronizationContext Implementations

 

Specific Thread Used to Execute Delegates

Exclusive (Delegates Execute One at a Time)

Ordered (Delegates Execute in Queue Order)

Send May Invoke Delegate Directly

Post May Invoke Delegate Directly

Windows Forms

Yes

Yes

Yes

If called from UI thread

Never

WPF/Silverlight

Yes

Yes

Yes

If called from UI thread

Never

Default

No

No

No

Always

Never

ASP.NET

No

Yes

No

Always

Always

0 0