SynchronizationContext,它何时流动,何时不流动?

时间:2014-12-01 13:07:21

标签: c# asynchronous task-parallel-library synchronizationcontext

我正在尝试了解SynchronizationContext和朋友。 如果我在例如开始时设置自定义同步上下文控制台应用。 在什么条件下,当前的同步上下文会与我的异步操作一起流动? Task与其他人之间是否存在差异,例如Delegate.BeginInvoke

void Main()
{
    SynchronizationContext.SetSynchronizationContext(new FooContext());
    Action a = () =>
    {
         var current = SynchronizationContext.Current;
         //current is null here
    };
    a.BeginInvoke(null,null);

    ...sleep

如果我在线程池上执行了东西,我是否被迫将同步上下文分配给当前正在执行我的工作的特定线程?

1 个答案:

答案 0 :(得分:5)

  

当前同步上下文在什么条件下会与我的异步操作一起流动?

async方法执行await时,默认情况下它会捕获当前上下文并使用它来恢复async方法。除非是SynchronizationContext.Current,否则此上下文为null,在此情况下为TaskScheduler.Current。我在async intro blog post,我的MSDN article on SynchronizationContext和我的MSDN article on async best practices中描述了这种行为。

  

任务与其他人之间是否存在差异,例如Delegate.BeginInvoke?

此行为对asyncawait是唯一的。 Delegate.BeginInvoke表示"在线程池线程"上运行此委托,因此它不会传播SynchronizationContext。也没有更多的现代方法,例如Task.Run

  

如果我在线程池上执行了东西,我是否被迫将同步上下文分配给当前正在执行我的工作的特定线程?

通常,您不应该在您不拥有的主题上安装同步上下文。如果您确实在线程池线程上放置了一个,则应在将线程返回到线程池之前将其删除。更有可能的是,如果您正在安装同步上下文,那么您就不应该回复该线程(自定义同步上下文通常与该主线的#34;主循环相关联)。

  在上面的示例中,

是逻辑调用上下文流,但不是同步上下文。任何指向这种情况的指针都会很有趣。

其他背景甚至没有记录。 Stephen Toub有definitive post on the subject。实质上,一些数据如安全必须流动;大多数其他数据没有。