为什么SynchronizationContext检查为null?

在try块中的WindowsFormsSynchronizationContext类的InstallIfNeeded方法 :

SynchronizationContext currentContext = AsyncOperationManager.SynchronizationContext; //Make sure we either have no [....] context //or that we have one of type SynchronizationContext if (currentContext == null || currentContext.GetType() == typeof(SynchronizationContext)) { ... 

首先,调用AsyncOperationManager.SynchronizationContext getter,并检查其返回值是否为null。 在这里检查是否需要null?

下面的AsyncOperationManager.SynchronizationContext代码。 它首先检查当前同步上下文是否为空,如果是,则创建一个新的。 所以这个getter可能永远不会返回null。

 public static SynchronizationContext SynchronizationContext { get { if (SynchronizationContext.Current == null) { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); } return SynchronizationContext.Current; } 

在这里检查是否需要null?

我之前的回答忽略了这样一个事实,即SynchronizationContext.Current实际上是基于线程创建的,而不是跨多个线程创建的(感谢@PerSerAl指出这一点)。 你可以在代码中看到它:

 // Get the current SynchronizationContext on the current thread public static SynchronizationContext Current { get { return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContext ?? GetThreadLocalContext(); } } 

实际上,这实际上使得null检查成为冗余,但确实可以避免将来可能发生的任何围绕SynchronizationContext实现编码的更改。

使用现在的确切代码,你是对的。

但是,请查看代码的意图 。 关键是安装winforms上下文的唯一安全点是没有其他同步上下文时。 这对应于具有null同步上下文或默认SynchronizationContext

在当前确切版本的代码中,同步上下文永远不能null的事实很大程度上是无关紧要的。 没错,这可能不会改变,因为它是一个公共静态接口,但依赖于它是一个完全不必要的依赖。 您希望您的代码尽可能清楚地表明其意图,并且此检查正是这样做 – 同时还避免直接依赖于公共接口的内部行为。

所以这就是我所看到的(前两位与您的问题相同):

 SynchronizationContext currentContext = AsyncOperationManager.SynchronizationContext; //Make sure we either have no [....] context or that we have one of type SynchronizationContext if (currentContext == null || currentContext.GetType() == typeof(SynchronizationContext)) { 

然后去:

 public static SynchronizationContext SynchronizationContext { get { if (SynchronizationContext.Current == null) { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); } return SynchronizationContext.Current; } 

然后导致: in the line (SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

 public static void SetSynchronizationContext(SynchronizationContext syncContext) { ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext(); ec.SynchronizationContext = syncContext; ec.SynchronizationContextNoFlow = syncContext; } 

但后来它返回了SynchronizationContext.Current

 public static SynchronizationContext Current { get { return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContext ?? GetThreadLocalContext(); } } 

哪个可能最终到此为止。

 private static SynchronizationContext GetThreadLocalContext() { SynchronizationContext context = null; #if FEATURE_APPX if (context == null && Environment.IsWinRTSupported) context = GetWinRTContext(); #endif return context; } 

如您所见,如果IsWinRTSupported返回false,则context可以为null。

基于我所看到的,空检查可能是一个好主意。 我不知道第一个条件Thread.CurrentThread.GetExecutionContextReader().SynchronizationContext可以返回null但是给出了?? 运营商,这是一种可能性。