Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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# 传递ExecutionContext(流)还是捕获它?_C#_.net_Multithreading - Fatal编程技术网

C# 传递ExecutionContext(流)还是捕获它?

C# 传递ExecutionContext(流)还是捕获它?,c#,.net,multithreading,C#,.net,Multithreading,从这里开始: Task.Run或ThreadPool.QueueUserWorkItem等方法会自动执行此操作。Run方法从调用线程捕获ExecutionContext并将其与任务实例一起存储。当与任务关联的TaskScheduler运行给定委托时,它将通过ExecutionContext运行该委托。使用存储的上下文运行 正常的ExecutionContext流和捕获之间有什么区别?对我来说,捕获意味着非常具体的事情——对象状态的快照。与此类似,闭包在匿名方法/本地方法等中捕获,其中闭包作为字

从这里开始:

Task.Run或ThreadPool.QueueUserWorkItem等方法会自动执行此操作。Run方法从调用线程捕获ExecutionContext并将其与任务实例一起存储。当与任务关联的TaskScheduler运行给定委托时,它将通过ExecutionContext运行该委托。使用存储的上下文运行

正常的
ExecutionContext
流和捕获之间有什么区别?对我来说,捕获意味着非常具体的事情——对象状态的快照。与此类似,闭包在匿名方法/本地方法等中捕获,其中闭包作为字段生成,其自身的值不再反映原始值源(变量)的状态

所以,当我们谈论捕获当前线程的上下文时,这和正常的上下文流有什么不同吗?例如,在正常流程中,状态总是最新的,因此如果父线程上的区域性发生更改,子线程会知道,但是如果捕获了
EC
,那么子线程现在只获取该时间捕获的快照?我理解正确吗?MSDN文档在“流”/“捕获”术语用法上确实不一致

现在,我们有一个非常重要的观察:flowing ExecutionContext在语义上与捕获和发布到SynchronizationContext非常不同

当您流动ExecutionContext时,您从一个线程捕获状态,然后恢复该状态,使其在所提供的委托执行期间处于环境状态。当您捕获并使用SynchronizationContext时,情况并非如此。捕获部分是相同的,因为您正在从当前线程获取数据,但随后使用不同的状态。使用SynchronizationContext.Post,而不是在调用委托时将该状态设置为当前状态,您只是使用捕获的状态来调用委托委托在何处、何时以及如何运行完全取决于Post方法的实现。


这对我来说没什么意义。捕获上下文并在其上发布(在带有UI线程的UI应用程序示例中)背后的想法是在相同的上下文中返回该线程(更新UI,duh)。但是,如果“委托在何处、何时以及如何运行完全取决于Post方法的实现”,那么您如何确保这一点呢?

这是一个众所周知的复杂主题,而Stephen Toub的文章(尽管很好)很难理解

ExecutionContext包含有关您的执行环境的“环境”信息。也就是说,例如,
SecurityContext
(保存在EC中)将被“流化”,这意味着线程池线程中的安全上下文与UI线程中的相同。它将一系列其他类似的细节对齐,以便在相同的环境中执行

在本例中,捕获与流动是保持对上下文的引用与使该上下文成为当前上下文之间的区别。因此,当我们在这样的任务上运行某些东西时:

public static void DoWork()
{

    var sc = SynchronizationContext.Current; <-- SC of UI thread is captured, so a reference has been created to the SC of the UI thread
    ThreadPool.QueueUserWorkItem(delegate
    {
        var scThreadPool = SynchronizationContext.Current; <-- thread pool thread has no SC associated so this is null
        … // do work on ThreadPool
        sc.Post(delegate <-- this is posting to the SC of the UI thread now
        {
            … // do work on the original context
        }, null);
   });
}

因此,执行上下文是流动的,这意味着它将成为线程池线程的执行上下文,但SC不会。最后一件令人困惑的事情是,SC实际上是执行上下文的一部分,并且可以(但通常不)流动。在大多数情况下,它不会流动,我们不需要担心它。

我认为你把它和。这是两件完全不同的事情。它们确实是,我是说它们在某个地方是一样的吗?你不是说它们是一样的,但是OP询问了
ExecutionContext
,你的答案大部分是关于捕获
SynchronizationContext
。除非我遗漏了什么,否则你的答案似乎与所问的问题毫不相关。我以为我在前半部分提到了执行上下文的流动,但我想这可能是因为我写了它:)我会重读它,看看是否可以编辑它以使其更清楚。
var scThreadPool = SynchronizationContext.Current;