6

我正在努力了解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

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

4

1 回答 1

5

在什么情况下,当前同步上下文将与我的异步操作一起流动?

async方法执行await时,默认情况下它将捕获当前上下文并使用它来恢复该async方法。这个上下文是SynchronizationContext.Current除非它是null,在这种情况下它是TaskScheduler.Current。我在我的async介绍性博客文章关于SynchronizationContextMSDN 的文章和关于异步最佳实践的 MSDN 文章中描述了这种行为。

Task 和其他的有区别吗,例如 Delegate.BeginInvoke?

async这种行为是和独有的awaitDelegate.BeginInvoke表示“在线程池线程上运行此委托”,因此它不会传播SynchronizationContext. 更现代的方法(例如Task.Run.

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

通常,您不应该在不属于您的线程上安装同步上下文。如果您确实将一个放在线程池线程上,则应在线程返回线程池之前将其删除。更有可能的是,如果您正在安装一个同步上下文,那么您永远不应该将线程返回(自定义同步上下文通常与该线程的“主循环”相关联)。

在上面的示例中,逻辑调用上下文流动但不是同步上下文。任何关于为什么会这样的指针都会很有趣。

其他上下文的记录更少。Stephen Toub 有关于这个主题的权威帖子。本质上,安全等一些数据必须流动;大多数其他数据没有。

于 2014-12-01T18:03:22.220 回答