【问题标题】:Can the current SynchronizationContext be null?当前的 SynchronizationContext 可以为空吗?
【发布时间】:2016-03-03 06:26:03
【问题描述】:

https://msdn.microsoft.com/en-us/magazine/gg598924.aspx

这是一篇很棒的文章,我知道无法涵盖所有​​细节,因为这基本上涉及粘贴 .NET 框架的源代码。所以引用正文:

每个线程都有一个当前上下文。 如果“Current”为空,则线程的当前上下文为 按照惯例,“new SynchronizationContext()”。

然而,另一方面:

默认情况下,当前的 SynchronizationContext 在等待时被捕获 点,并且这个 SynchronizationContext 用于在 await (更准确地说,它捕获当前的 SynchronizationContext 除非它是 null,在这种情况下它会捕获当前 任务调度器)

这两个陈述几乎相互矛盾,所以我认为这是作者所做的一些简化的结果(我很好)。

谁能解释一下? Code 可能有助于回答我的问题(查找 syncCtx 变量),这段代码与第二个引用有关。

【问题讨论】:

  • 这并不矛盾 - 同步上下文 可以 为空 - 只是为了继续处理,没有任务调度程序的空同步上下文等效于 @987654325 @。 “按照惯例”只是捕获同步上下文的处理方式,它不是禁止空同步上下文的规则。至于代码,它是公开的——referencesource.microsoft.com/#mscorlib/system/threading/…

标签: c# multithreading synchronizationcontext


【解决方案1】:

您要查找的相关代码在内部方法Task.SetContinuationForAwait 中:

// First try getting the current synchronization context.
// If the current context is really just the base SynchronizationContext type, 
// which is intended to be equivalent to not having a current SynchronizationContext at all, 
// then ignore it.  This helps with performance by avoiding unnecessary posts and queueing
// of work items, but more so it ensures that if code happens to publish the default context 
// as current, it won't prevent usage of a current task scheduler if there is one.
var syncCtx = SynchronizationContext.CurrentNoFlow;
if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
{
    tc = new SynchronizationContextAwaitTaskContinuation(
                syncCtx, continuationAction, flowExecutionContext, ref stackMark);
}
else
{
    // If there was no SynchronizationContext, then try for the current scheduler.
    // We only care about it if it's not the default.
    var scheduler = TaskScheduler.InternalCurrent;
    if (scheduler != null && scheduler != TaskScheduler.Default)
    {
        tc = new TaskSchedulerAwaitTaskContinuation(
                scheduler, continuationAction, flowExecutionContext, ref stackMark);
    }
}

它实际上做了两个检查,第一个检查它不是null,第二个检查它不是默认的SynchronizationContext,我认为这是关键点这里。

如果您打开一个控制台应用程序并尝试获取SynchronizationContext.Current,您肯定会看到它可以是null

class Program
{
    public static void Main(string[] args)
    { 
        Console.WriteLine(SynchronizationContext.Current == null ? "NoContext" :
                                                                   "Context!");
    }
}

【讨论】:

  • 那我该如何理解如果“Current”为空,那么线程的当前上下文是“new SynchronizationContext()”,按照惯例。?现在我意识到作者可能指的是我上一个问题中的第二个代码 sn-p:stackoverflow.com/questions/33867387/…
  • 我不确定 Stephan Cleary 写这篇文章时的意思。也许他说的是AsyncOperatonManager,它总是设置默认的SynchronizationContext
  • 这是两种不同的上下文。较早的文章仅涉及SynchronizationContext,它确实具有将null 视为new SynchronizationContext 的约定,例如,对于EAP 组件。 await 定义了自己的上下文,但略有不同。如果你想扭曲你的大脑,Toub 有一篇关于更多背景的文章。
  • @StephenCleary 我明白了。我在哪里可以找到它?我看过很多 Stephen Toub 的博文,但可能还没有遇到过。
  • @user4205580:对不起;当我写最后一条评论时,它在我的新平板电脑上,这很痛苦。说真的,屏幕键盘占据了大约 70% 的屏幕!反正博文是here
猜你喜欢
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
相关资源
最近更新 更多