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

时间:2019-07-22 17:25:45

标签: .net asynchronous lambda async-await task-parallel-library

我需要了解这三种使用TPL分解任务的方式之间的区别:

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

vs。

Task.Run(_client.RunClient);

vs。

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

假设我具有以下类结构:

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是否立即返回,并且函数继续执行?还是仅在方法_client.RunClient完成时才完成Task.Run?什么是_client.RunClient在while(true)循环中并且永不退出?这对每种纺纱方法有何影响?

围绕这些调用任务的不同方式的最佳实践是什么?我要等λ吗?我是否在等待Task.Run?我不等待_client.RunClient吗?

很抱歉,一篇帖子中的所有问题。我正在尝试理解这些不同的行为,因此我可以选择最有意义的行为。我已经阅读了很多有关异步/等待的内容,这是我似乎找不到答案的一个问题。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

  

我需要了解这三种任务分解方式之间的区别

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

这些几乎都是相同的。第一个传递一个lambda,然后将其转换为委托。第二个方法传入一个方法组,该方法组将转换为委托;第三个传递一个lambda,然后将其转换为具有async状态机的委托。

但是就语义而言,它们实际上都是相同的。第三个开销稍大,但是实际应用中的开销很可能很小。

  

Task.Run是否立即返回,并且函数继续执行?

Task.Run立即返回Task

  

或者Task.Run仅在方法_client.RunClient完成时完成吗?

这取决于您完成Task.Run的意思。它立即返回一个任务,但是当某个方法返回一个任务时,则该任务表示该方法的执行。 Task.Run返回的任务将在RunClient完成时完成。

  

什么是_client.RunClient在while(true)循环中并且永不退出?这对每种纺纱方法有何影响?

然后Task.Run返回的任务将永远不会完成。

  

围绕这些调用任务的不同方式的最佳实践是什么?我要等λ吗?我是否在等待Task.Run?我不等待_client.RunClient吗?

  1. await个任务。除非您不应该这样做(例如,任务无法完成)。
  2. Don't use Task.Run。除非您需要这样做(例如,将与CPU绑定的代码移出UI线程,或者强制执行线程池上下文)。
  3. 请勿elide async and await。除非这是一个简单的方法,例如本例中的lambda。