我正在努力了解
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
如果我在线程池上执行东西,我是否被迫将同步上下文分配给当前正在执行我的工作的特定线程?
在什么条件下当前同步上下文会与我的异步操作一起流动?
当
async
方法执行 await
时,默认情况下它将捕获当前上下文并使用它来恢复 async
方法。此上下文是 SynchronizationContext.Current
,除非它是 null
,在这种情况下它是 TaskScheduler.Current
。我在我的 async
介绍性博文、关于 SynchronizationContext
的 MSDN 文章以及关于异步最佳实践的 MSDN 文章中描述了这种行为。
Task 和其他任务之间是否存在差异,例如:委托.BeginInvoke?
此行为是
async
和 await
所独有的。 Delegate.BeginInvoke
表示“在线程池线程上运行此委托”,因此它不会传播 SynchronizationContext
。 Task.Run
等更现代的方法也没有。
如果我在线程池上执行东西,我是否被迫将同步上下文分配给当前正在执行我的工作的特定线程?
一般来说,您不应该在不属于您的线程上安装同步上下文。如果您确实在线程池线程上放置了一个线程,则应在线程返回到线程池之前将其删除。更有可能的是,如果您正在安装同步上下文,您就不应该将线程返回(自定义同步上下文通常与该线程的“主循环”相关联)。
在上面的示例中,逻辑调用上下文流动,但同步上下文不流动。任何说明为什么会出现这种情况的指示都会很有趣。
其他上下文的记录甚至更少。 Stephen Toub 发表了关于该主题的权威文章。从本质上讲,一些数据(例如安全性)必须流动;大多数其他数据没有。