🗒️ExecutionContext vs SynchronizationContext
2023-12-21
| 2023-12-21
0  |  0 分钟
type
status
date
slug
summary
tags
category
icon
password

关于ExecutionContext

ExecutionContext is all about “ambient” information, meaning that it stores data relevant to the current environment or “context” in which you’re running.
ExecutionContext 都是关于环境信息的,这意味着它存储了与当前运行相关的环境或者上下文。
 
There is, however, typically a logical flow of control, and we want this ambient data to flow with that control flow, such that the ambient data moves from one thread to another. This is what ExecutionContext enables.
然而,通常存在一种逻辑控制流,并且我们希望环境数据随着该控制流动,使得环境数据能够从一个线程传递到另一个线程。这就是ExecutionContext所实现的功能。
 
ExecutionContext is really just a state bag that can be used to capture all of this state from one thread and then restore it onto another thread while the logical flow of control continues.
ExecutionContext实际上就是一个状态包,可以用来捕获一个线程的所有状态,然后在逻辑控制流继续的同时将这些状态恢复到另一个线程。

关于SynchronizationContext

SynchronizationContext is just an abstraction, one that represents a particular environment you want to do some work in.
SynchronizationContext 只是一个抽象,它代表你想在其中进行一些工作的特定环境。
 
Windows Forms provides the WindowsFormSynchronizationContext type which overrides Post to call Control.BeginInvoke. WPF provides the DispatcherSynchronizationContext type which overrides Post to call Dispatcher.BeginInvoke.
例如WinformWindowsFormSynchronizationContext , WPFDispatcherSynchronizationContext

如何应用于async/await

The framework support behind the async and await keywords automatically interacts with both ExecutionContext and SynchronizationContext.
异步(async)和等待(await)关键字背后的框架支持会自动与 ExecutionContextSynchronizationContext进行交互。
 
When you await a task, by default the awaiter will capture the current SynchronizationContext, and if there was one, when the task completes it’ll Post the supplied continuation delegate back to that context, rather than running the delegate on whatever thread the task completed or rather than scheduling it to run on the ThreadPool.
当你在等待一个任务时,在默认情况下,等待器将会捕捉当前的同步上下文当存在时。当任务完成后,它将会把所提供的延续委托送回到那个上下文中,而不是在完成任务的线程中或者安排在线程池中运行。
 
Whereas this behavior is always employed when you await a Task or Task<TResult>, you can instead await the result of calling task.ConfigureAwait(…).The awaiter doesn’t check for a SynchronizationContext, pretending as if there wasn’t one.
你可以使用task.ConfigureAwait(false)等待结果来取代默认的行为。
 
In fact, as I’ve stated in other posts, most library implementers should consider using ConfigureAwait(false) on every await of a task.
实际上,正如我在其他帖子中所述,大多数库实现者应该在每个等待任务的地方都考虑使用ConfigureAwait(false)以防调用者同步阻塞调用,导致UI线程发送死锁
 

SynchronizationContext是不是ExecutionContext的一部分

The main thing I glossed over is that of all the contexts ExecutionContext is capable of flowing (e.g. SecurityContext, HostExecutionContext, CallContext, etc.), SynchronizationContext is actually one of them.
SynchronizationContext 被包含在ExecutionContext 中。
 
In short, SynchronizationContext.Current does not “flow” across await points.
Task.Run[会调用TaskFactory.StartNew]中,捕捉ExecutionContext 会忽略对SynchronizationContext 的捕捉。
Thread.Run 中也有类似的情形。
 
不会出现后台线程中,await 后使用UI线程进行Compute(data) 操作,造成UI线程阻塞卡顿。此时SynchronizationContext==null ,将使用ThreadPool中线程完成延续任务。
 

参考链接

 
技术分享
  • 开发
  • .NET
  • C#程序等待的几种方法解析C#程序等待的几种方法解析
    目录