我什么时候需要担心导致多线程的任务?

时间:2017-04-07 07:18:56

标签: c# .net multithreading asynchronous async-await

说我有这样的代码:

...
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限制的工作,所以我使用锁或其他东西(之前从未使用过)?

1 个答案:

答案 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.
  }
}