- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
This article来自 SynchronizationContext
可能与 ExecutionContext
一起流动的状态:
private void button1_Click(object sender, EventArgs e) {
button1.Text = await Task.Run(async delegate
{
string data = await DownloadAsync();
return Compute(data);
});
}Here’s what my mental model tells me will happen with this code. A user clicks button1, causing the UI framework to invoke button1_Click on the UI thread. The code then kicks off a work item to run on the ThreadPool (via Task.Run). That work item starts some download work and asynchronously waits for it to complete. A subsequent work item on the ThreadPool then does some compute-intensive operation on the result of that download, and returns the result, causing the Task that was being awaited on the UI thread to complete. At that point, the UI thread processes the remainder of this button1_Click method, storing the result of the computation into the button1’s Text property.
My expectation is valid if SynchronizationContext doesn’t flow as part of ExecutionContext. If it does flow, however, I will be sorely disappointed. Task.Run captures ExecutionContext when invoked, and uses it to run the delegate passed to it. That means that the UI SynchronizationContext which was current when Task.Run was invoked would flow into the Task and would be Current while invoking DownloadAsync and awaiting the resulting task. That then means that the await will see the Current SynchronizationContext and Post the remainder of asynchronous method as a continuation to run back on the UI thread. And that means my Compute method will very likely be running on the UI thread, not on the ThreadPool, causing responsiveness problems for my app.
The story now gets a bit messier: ExecutionContext actually has two Capture methods, but only one of them is public. The internal one (internal to mscorlib) is the one used by most asynchronous functionality exposed from mscorlib, and it optionally allows the caller to suppress the capturing of SynchronizationContext as part of ExecutionContext; corresponding to that, there’s also an internal overload of the Run method that supports ignoring a SynchronizationContext that’s stored in the ExecutionContext, in effect pretending one wasn’t captured (this is, again, the overload used by most functionality in mscorlib). What this means is that pretty much any asynchronous operation whose core implementation resides in mscorlib won’t flow SynchronizationContext as part of ExecutionContext, but any asynchronous operation whose core implementation resides anywhere else will flow SynchronizationContext as part of ExecutionContext. I previously mentioned that the “builders” for async methods were the types responsible for flowing ExecutionContext in async methods, and these builders do live in mscorlib, and they do use the internal overloads… as such, SynchronizationContext is not flowed as part of ExecutionContext across awaits (this, again, is separate from how task awaiters support capturing the SynchronizationContext and Post’ing back to it). To help deal with the cases where ExecutionContext does flow SynchronizationContext, the async method infrastructure tries to ignore SynchronizationContexts set as Current due to being flowed.
不过,我不太清楚什么时候这可能会发生。它似乎会在使用公共(public) ExecutionContext.Capture
方法和抑制流动 SynchronizationContext
与 的内部
未被使用,但我不知道那会是什么时候。Task.Run
重载时发生>ExecutionContext
在我对 .NET 4.5 的测试中,Task.Run
似乎没有使 SynchronizationContext
与 ExecutionContext
流动:
private async void button1_Click(object sender, EventArgs e) {
Console.WriteLine("Click context:" + SynchronizationContext.Current);
button1.Text = await Task.Run(async delegate {
// In my tests this always returns false
Console.WriteLine("SynchronizationContext was flowed: " + (SynchronizationContext.Current != null));
string data = await DownloadAsync();
return Compute(data);
});
}
所以我的问题是在什么情况下 Compute()
会像文章中讨论的那样在 UI 上下文(阻塞 UI 线程)上运行?
最佳答案
When does Task.Run flow SynchronizationContext with ExecutionContext?
从不。
那篇文章的要点是(用于)流动ExecutionContext
的(公共(public)API)将流动SynchronizationContext
。但是 Task.Run
(以及“几乎所有其核心实现驻留在 mscorlib 中的异步操作”)永远不会这样做。
以“我的期望是有效的”开头的段落是假设性的。他正在描述如果 Task.Run
使用公共(public) API 来流动 ExecutionContext
时会发生什么。这会导致问题如果它这样做了。这就是它从不这样做的原因。
关于c# - Task.Run 什么时候流 SynchronizationContext 和 ExecutionContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19548389/
这个问题在这里已经有了答案: Why use async and return await, when you can return Task directly? (8 个答案) 关闭 6 年前。
这个问题在这里已经有了答案: Are the days of passing const std::string & as a parameter over? (13 个答案) 关闭 8 年前。 我
我有一组标记为执行的通用任务。当任务完成时(使用 Task.WaitAny ),我将其添加到 ObservableCollection 中. 但是,问题出在 Task.WaitAny(...)行,上面
经过几个小时的努力,我在我的应用程序中发现了一个错误。我认为下面的 2 个函数具有相同的行为,但事实证明它们没有。 谁能告诉我引擎盖下到底发生了什么,以及为什么它们的行为方式不同? public as
这也与 Python 的导入机制有关,特别是与在函数内使用 import 有关。使用 Python 2.7.9 和 Fabric 1.10.0,创建以下三个文件: fabfile.py: from a
我有一个 Web API Controller (ASP.NET Core 5)。我的一些 API 是异步的,而其中一些不是。我接下来的问题是:使用 public **Task** WebApiMet
我们有类似下面的内容 List uncheckItems = new List(); for (int i = 0; i new Task(async () => await Process
我的代码没问题,但我想知道哪种风格更好,你会怎么看,我正在玩异步方法。 让我建立上下文: Parallel.ForEach(xmlAnimalList, async xml => {
这两种使用 await 的形式在功能上有什么区别吗? string x = await Task.Factory.StartNew(() => GetAnimal("feline")); Task m
我刚刚看到 3 个关于 TPL 使用的例程,它们做同样的工作;这是代码: public static void Main() { Thread.CurrentThread.Name = "Ma
考虑以下代码: public void CacheData() { Task.Run((Action)CacheExternalData); Task.Run(() => CacheE
Task> GetTaskDict() { return Task.FromResult(new Dictionary () ); } 此代码无法编译,因为我们无法在 Task> 到 Tas
我正在使用 ASP.NET 5 RC1 _MyPartial @model MyViewModel @using (Html.BeginForm())
当我尝试在 VS Code 中构建 C 任务时,它显示以下消息: 输出仅显示:The task provider for "C/C++" tasks unexpectedly provided a t
一些背景: 基本上归结为我希望能够在当前线程中“执行”任务。为什么? -我有一个任务创建程序例程,有一次我希望任务在后台任务中立即执行,而其他时候我希望使用 IOmniThreadPool 安排任务。
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我试图将run-sequence添加到我的gulp工作流程中,但是每次尝试执行使用run-sequence的任务时,都会出现此错误: 任务未配置为gulp上的任务。 根据运行序列的来源,这是由以下te
此代码在VS2015中给出了编译时错误 Error CS0266 Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'Sy
我正在尝试通过我的代码通过Google登出: suspend fun signOut(context: Context): Boolean = with(Dispatchers.IO) { t
谁能解释一下这两种说法的区别: Task bTask = backup.BackupCurrentDatabaseAsync() .ContinueWith(_ => CompressArch
我是一名优秀的程序员,十分优秀!