对于 .NET,等待任务完成的最佳方式是什么?

What is the best way to wait for a task to finish with respect to .NET?

这是我们的async方法,在Task中执行了很长时间。

public async Task<int> LongRunningMethod(T p1, T p2, T p3);

我团队中的一些开发人员使用

Task t = Task.Factory.StartNew(LongRunningMethod(p1,p2,p3));
t.Wait();  //This will suspend main thread and wait for 't' to finish.

虽然有些人使用

await LongRunningMethod(p1,p2,p3);
// Here too, we simply 'await' till the method finishes.

注意:我们有一个异步任务,我们想等到该任务完成。

简而言之,以上两种结构中哪一种最好?

使用任务的要点是从相同的上下文中并行执行一些任务。如果你想从上下文开始一个长 运行 任务并且只想等待任务完成,你展示的两种方法都将以相同的方式工作。

但是如果你想在执行长运行任务的过程中做任何其他操作, 你可以这样做

Task taskObj = LongRunningMethod();
/// Do some other operations here...
var result = await taskObj;

但是如果需要长 运行 任务的结果来执行某些操作,则需要等待任务完成。 或者你可以使用 Task.ContinueWith()

In short, Which one is the best among the above two constructs ?

你会知道影响,当系统可伸缩性出现时,Task.Wait()await Task 之间的区别是它们对待调用/执行线程的方式。当第一个会阻塞直到完成发生时,另一个使用 await 会释放调用者,但请注意它只用于真正的异步调用,这意味着 IO 调用、网络调用、数据库调用不是在内存逻辑处理中,并公开异步 API,即调用线程或释放上下文时。对于真正的异步调用,它将使用 windows 中的 IO 完成端口(排队机制)来执行异步管道。

如果调用链末尾的 final 方法不是真正的 Async,则不会发生这种情况。

They look almost similar Wait and await

确实,对于两个延续都将执行 post 完成,但让我们举个例子,通常被处理的线程直接与系统中的核心数相关联,使用 TPL 这些线程是从池中调用的并且可用线程数有限制。对于像 100 K / 秒请求这样的高可扩展系统,Task.Wait() 会很快超时一个长的 运行 方法,因为线程忙于闲置并被阻塞,它们不会接受新请求,但是对于 await 根本没有这样的阻塞发生。

Practical examples

  • Javascript, NodeJs 默认总是异步请求,没有阻塞,这就是系统高度可扩展的原因

  • 再考虑ConfigureAwait(false),加上await,就不会去寻找相同的线程上下文重新进入继续执行,这样效率更高