说我有这样的代码:
...
var task1 = DoWorkAsync(1);
var task2 = DoWorkAsync(2);
await Task.WhenAll(task1, task2);
...
private async Task DoWorkAsync(int n)
{
// Async HTTP request that we ConfigureAwait(to be determined).
// Some CPU-bound work that isn't thread-safe.
}
因此,如果我使用的是WPF应用,并且我没有ConfigureAwait(false)
发出HTTP请求,那么我在这里安全吗?这两个HTTP请求可以同时进行,但任务必须在UI线程上恢复,因此CPU绑定的工作不是多线程的?但是如果我ConfigureAwait(false)
,那么任务可以在不同的线程池线程上并行恢复CPU绑定工作,这样我就麻烦了吗?
如果我在ASP.NET中,它可以以任何一种方式发生,因为同步上下文与WPF之类的线程无关?
如果我在控制台应用程序中该怎么办?
我如何谈论DoWorkAsync
?我是否同时说DoWorkAsync
并不安全?
有没有正常的方法来重新设计它?同时执行的重要部分是HTTP请求,而不是CPU限制的工作,所以我使用锁或其他东西(之前从未使用过)?
答案 0 :(得分:1)
因此,如果我在WPF应用程序中并且我在HTTP请求上没有ConfigureAwait(false),我在这里安全吗?
如果在UI线程上调用它,那么是的,你是对的。 UI上下文一次只允许一个线程(UI线程是特定的),因此CPU绑定部分将在UI线程上运行而不会相互干扰。这是一个非常常见的技巧。
如果我执行ConfigureAwait(false),任务可以在不同的线程池线程上并行恢复CPU绑定工作,这样我就麻烦了吗?
是。因为ConfigureAwait(false)
表示“受CPU限制的工作不需要上下文”,所以它可以在线程池上并行运行。
如果我在ASP.NET
Classic ASP.NET具有一次一个线程的请求上下文,因此它的行为相同;如果没有ConfigureAwait(false)
,那就安全了。
ASP.NET Core 不有一个请求上下文(好吧,不管是SynchronizationContext
),所以它可以在该平台上并行运行。我称之为"implicit parallelism" in my blog post on the ASP.NET Core SynchronziationContext。
如果我在控制台应用程序中该怎么办?
没有上下文,因此它可以并行运行。
我如何谈论DoWorkAsync?
“此方法需要非自由线程SynchronizationContext
。”
我使用锁或其他东西
这是最好的方法,是的:
private readonly object _mutex = new object();
private async Task DoWorkAsync(int n)
{
await HttpRequestAsync().ConfigureAwait(false);
lock (_mutex)
{
// Some CPU-bound work that isn't thread-safe.
}
}