【发布时间】:2020-07-10 13:02:31
【问题描述】:
为什么 ThreadPool 决定使用名为 Task.Wait 的确切上下文线程?
有the question。由于某些原因,我既没有看到问题的评论按钮,也没有看到任何答案的评论按钮。所以,我在一个单独的线程中问了一个相关的问题。
在链接的问题中有一个指向the blog 的答案。根据此博客,以下声明成立。
有代码片段:
// My "library" method.
public static async Task<JObject> GetJsonAsync(Uri uri)
{
// (real-world code shouldn't use HttpClient in a using block; this is just example code)
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
}
// My "top-level" method.
public void Button1_Click(...)
{
var jsonTask = GetJsonAsync(...);
textBox1.Text = jsonTask.Result;
}
还有死锁发生的解释:
- 顶级方法调用
GetJsonAsync(在 UI/ASP.NET 上下文中)。GetJsonAsync通过调用HttpClient.GetStringAsync(仍在上下文中)启动 REST 请求。GetStringAsync返回未完成的Task,表示 REST 请求未完成。GetJsonAsync等待由GetStringAsync返回的Task。上下文被捕获并将用于稍后继续运行GetJsonAsync方法。GetJsonAsync返回一个未完成的Task,表示GetJsonAsync方法没有完成。- 顶级方法同步阻塞
GetJsonAsync返回的任务。这会阻塞上下文线程。- ... 最终,REST 请求将完成。这完成了由
GetStringAsync返回的Task。GetJsonAsync的延续现在已准备好运行,它等待上下文可用,以便在上下文中执行。- 死锁。顶级方法是阻塞上下文线程,等待
GetJsonAsync完成,而GetJsonAsync正在等待上下文空闲以便它可以完成。
我的问题特别是关于第 7 步。为什么ThreadPool 决定采用一个阻塞的线程并等待它解除阻塞以要求该线程运行代码?为什么不直接拿其他线程呢?
【问题讨论】:
-
“由于某些原因,我没有看到问题和任何答案的评论按钮。” 您还没有足够的声望点。如果你有所收获,你将能够发表评论。应该记录在help center 部分的某处。
-
问题:这是默认行为,因为通常,您需要从 GUI 线程中异步一些东西,之后,您需要继续使用该 GUI 线程,因为您想要使用异步调用的结果来操作 GUI 元素。请注意,该示例可能是故意使用错误代码编写的。另请注意:您可以在每次通话的基础上关闭此默认行为:Task.ConfigureAwait(bool)
-
@Fildor,所以这里的问题如下。 ThreadPool 可能会尝试决定使用产生任务的同一线程在任务的
await之后继续执行。并且线程池的(系统)配置可能会发生这样的情况,即线程池使用同一线程(即上下文)继续执行比使用非阻塞线程具有更高的优先级。我理解正确吗? -
也许“大师”本人可以比我更好地解释这一点:Async and Await - “上下文”部分
-
ThreadPool不决定与此相关的任何事情。决策由 async-await 机制做出。
标签: c# multithreading task threadpool deadlock