Task.Run(方法组)与 Task.Run(lambda)

Task.Run(method group) vs. Task.Run(lambda)

我需要知道使用 TPL 启动任务的这三种方式之间的区别:

Task.Run(() => _client.RunClient());

对比

Task.Run(_client.RunClient);

对比

Task.Run(async () => await _client.RunClient());

假设我有以下 class 结构:

public class Controller {

  private _client = new Client();

  ...

  public async Task StartClientA() {
    await Task.Run(_client.RunClient);
  }

  public async Task StartClientB() {
    await Task.Run(() => _client.RunClient());
  }

  public async Task StartClientC() {
    await Task.Run(async () => await _client.RunClient());
  }
}

然后,在客户端中,以下是每个 StartClientA、StartClientB 和 StartClientC 的方法签名:

public async Task StartClientA() {
  ...
}

public async Task StartClientB() {
  ...
}

public async Task StartClientC() {
  ...
}

现在,我在这些方法中调用 RunClient 的方式有何不同?

令我困惑的是后面的代码发生了什么:

await Task.Run(...)

是否立即Task.Run return,函数继续执行?还是 Task.Run 仅在方法 _client.RunClient 完成时才完成?什么是 _client.RunClient 处于 while(true) 循环中并且永不退出?这对这些启动线程的方法有何影响?

关于调用任务的这些不同方式的最佳实践是什么?我要等待 lambda 吗?我要等待 Task.Run 吗?我不等待_client.RunClient吗?

抱歉所有问题都在一个 post 中。我试图理解这些不同的行为,以便我可以选择最有意义的行为。我读过很多关于 async/await 的文章,这是一个我似乎找不到答案的问题。

在此先感谢您的帮助。

I need to know the difference between these three ways of spinning up a Task

Task.Run(() => _client.RunClient());
Task.Run(_client.RunClient);
Task.Run(async () => await _client.RunClient());

这些都差不多。第一个传入一个 lambda,它被转换为一个委托;第二个传入一个方法组,它被转换为一个委托;第三个传入一个 lambda,它被转换为一个具有 async 状态机的委托。

但就语义而言,它们几乎都是一样的。第三个开销稍微多一些,但在您的实际应用程序中,开销量很可能小得无法估量。

Does Task.Run return immediately, and the function continues executing?

Task.Run马上returns一个Task.

Or does Task.Run complete only when the method _client.RunClient completes?

这取决于您所说的 Task.Run 完成是什么意思。它立即returns一个任务,但是当一个方法returns一个任务时,那么那个任务代表那个方法的执行。 Task.Run 返回的任务将在 RunClient 完成时完成。

What is _client.RunClient is in a while(true) loop and never exits? How does that impact each of these methods of spinning up a thread?

那么 Task.Run 返回的任务永远不会完成。

What is best practice around these different ways of invoking a Task? Do I await the lambda? Do I await the Task.Run? Do I not await _client.RunClient?

  1. await 个任务。除非你不应该(例如,任务没有完成)。
  2. Don't use Task.Run。除非您需要(例如,将 CPU-bound 代码移出 UI 线程,或强制执行线程池上下文)。
  3. 不要elide async and await。除非它是一个微不足道的方法,例如本例中的 lambda。