Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SynchronizationContext是否不再与ExecutionContext一起流动(从.NET Framework到.NET Core)? tl;博士_C#_.net_.net Core - Fatal编程技术网

C# SynchronizationContext是否不再与ExecutionContext一起流动(从.NET Framework到.NET Core)? tl;博士

C# SynchronizationContext是否不再与ExecutionContext一起流动(从.NET Framework到.NET Core)? tl;博士,c#,.net,.net-core,C#,.net,.net Core,在.NET Framework中,SynchronizationContext是ExecutionContext传递的上下文之一。在.NETCore中不再是这样了吗 长问题 Stephen Toub在2012年的博客文章中写道,SynchronizationContext是ExecutionContext的一部分: SynchronizationContext不是ExecutionContext的一部分吗 到目前为止,我已经掩盖了一些细节,但我不能再回避它们了 我要强调的主要一点是,在所有的上下

在.NET Framework中,SynchronizationContext是ExecutionContext传递的上下文之一。在.NETCore中不再是这样了吗

长问题 Stephen Toub在2012年的博客文章中写道,SynchronizationContext是ExecutionContext的一部分:

SynchronizationContext不是ExecutionContext的一部分吗

到目前为止,我已经掩盖了一些细节,但我不能再回避它们了

我要强调的主要一点是,在所有的上下文中,ExecutionContext都能够流动(例如SecurityContext、HostExecutionContext、CallContext等),SynchronizationContext实际上就是其中之一。我个人认为,这是API设计中的一个错误,自从它在许多版本之前在.NET中建立以来,造成了一些问题。然而,这是我们已经拥有的设计,并且已经拥有很长时间了,现在改变它将是一个突破性的改变

这篇博文接着详细阐述了同步上下文何时作为ExecutionContext的一部分被传输,以及该传输何时被抑制:

故事现在变得有点混乱:ExecutionContext实际上有两种捕获方法,但其中只有一种是公共的。内部(mscorlib的内部)是从mscorlib公开的大多数异步功能所使用的,并且它允许调用方选择性地禁止捕获SynchronizationContext作为ExecutionContext的一部分;与此对应,Run方法还有一个内部重载,它支持忽略存储在ExecutionContext中的SynchronizationContext,实际上是假装没有捕获一个(这也是mscorlib中大多数功能使用的重载)。这意味着,其核心实现位于mscorlib中的任何异步操作都不会将SynchronizationContext作为ExecutionContext的一部分流动,但其核心实现位于其他任何位置的任何异步操作都会将SynchronizationContext作为ExecutionContext的一部分流动

然而,Stephen Toub在这里清楚地谈到了.NET框架,并且通过阅读一些源代码了解了ExecutionContext是如何在.NET Core中实现的,这似乎在.NET Core中已经发生了变化。在更现代的.NET核心实现中找不到作为内部.NET Framework ExecutionContext方法一部分的布尔
preserveSyncCtx
参数

但是对于.NET Framework和.NET Core来说,情况是一样的,并且

ExecutionContext类为与逻辑执行线程相关的所有信息提供了一个容器。这包括安全上下文、调用上下文和同步上下文

无论压缩堆栈流向何处,托管主体、同步、区域设置和用户上下文也会流向何处

这似乎表明SynchronizationContext仍然应该是ExecutionContext的一部分

为了尝试找出两者之间是否存在差异,我编写了以下NUnit测试:

使用System.Runtime.CompilerServices;
使用系统线程;
使用System.Threading.Tasks;
使用NUnit.Framework;
[测试夹具]
公共类ExecutionContextFlowTests
{
私有类TestSynchronizationContext:SynchronizationContext
{
/// 
公共覆盖同步上下文CreateCopy()
{
返回新的TestSynchronizationContext();
}
/// 
公共覆盖布尔等于(对象对象对象)
{
返回obj为TestSynchronizationContext;
}
/// 
公共覆盖int GetHashCode()
{
返回0;
}
}
[测试]
公共异步任务测试()
{
/*安排*/
var syncCtx=新的TestSynchronizationContext();
任务t;
使用(ExecutionContext.SuppressFlow())
{
t=Task.Run(()=>
{
SynchronizationContext prevCtx=SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(syncCtx);
尝试
{
返回ExecutionContext.Capture();
}
最后
{
SynchronizationContext.SetSynchronizationContext(prevCtx);
}
});
}
ExecutionContext capturedContext=await t.ConfigureAwait(false);
Assert.That(capturedContext,Is.Not.Null);
Assert.That(SynchronizationContext.Current,Is.Not.EqualTo(syncCtx));
/*表演*/
var syncCtxBox=new StrongBox();
ExecutionContext.Run(
capturedContext,
box=>((StrongBox)box).Value=SynchronizationContext.Current,
syncCtxBox
);
Assert.That(syncCtxBox.Value,Is.EqualTo(syncCtx));
}
}
还有,瞧,断言,但是(我使用了.NETFramework4.2.7和.NETCore3.1)


所以我的问题是:博客帖子和Microsoft文档是否已经过时,Stephen Toub所说的“API设计错误”在.NET Core中已经“修复”,还是我遗漏了什么?

看起来在.NET Core中,至少在当前的3.1版中,
ExecutionContext
不再捕获
SynchronizationContext
。看到了。但是,如果同步上下文在
ExecutionContext.Run
回调中发生了更改,它将被恢复


我认为这是有道理的,因为对于.NET内核,
SynchronizationContext
只与前端代码真正相关。他们的目标是尽可能地优化服务器端代码,因此他们删除了这一部分。

微软已经承认,
ExecutionContext
行为确实随着.NET Core的出现而发生了变化,并在一份声明中对此进行了澄清。作为变更的一部分,他们添加了以下句子:

A