什么时候多个等待是有意义的
本文关键字:有意义 等待 什么时候 | 更新日期: 2023-09-27 18:22:47
我对c#async/await机制有一些误解。之间有什么本质区别吗
private async void Init()
{
await Task.Run(() => Do1());
await Task.Run(() => Do2());
}
和
private async void Init()
{
await Task.Run(() =>
{
Do1();
Do2();
});
}
我看到的唯一区别是:在第一个示例中,Do1和Do2将在不同的线程中运行,而在第二个示例中——在同一个线程中。但是,它的真正好处是什么?什么时候我应该更喜欢第一种方法而不是第二种方法,反之亦然?
编辑:第二种情况
有什么区别
private async void Init()
{
await Task.Run(() => Do1());
Do3();
}
和
private async void Init()
{
await Task.Run(() =>
{
Do1();
Do3();
});
}
区别在于:
第一个例子:
- 在线程池线程上对
Do1
进行排队并异步等待它完成,然后对Do2
执行完全相同的操作。这些可能在不同的线程上运行 - 将
Do1
和Do2
排队,以便在同一线程池线程上一个接一个地同步执行
第二个例子:
- 在线程池上对
Do1
进行排队并异步等待其完成,然后同步调用Do3
- 这与第一个示例的第二部分完全相同
请注意,当您await
时,您异步地等待操作完成,因此,除非该方法完成,否则它不会执行下一行代码。
我假设你在问自己,一个是否比另一个更可取,在大多数情况下,这取决于情况。如果您在控制台应用程序中运行,并且无论如何都要异步等待Do1
完成,那么将两个方法传递给同一个Task.Run
调用。如果您计划在同步很重要的地方(例如GUI应用程序)执行此操作,那么任何需要与UI控件交互的操作都应该在UI线程上调用。
另一种更常见的选择是,当您有两个彼此独立的操作,并且您想一起启动它们并等待两者完成时。这就是您使用Task.WhenAll
:的地方
var firstDo = Task.Run(() => Do1());
var secondDo = Task.Run(() => Do2());
await Task.WhenAll(firstDo, secondDo);
旁注:
不要在没有返回值的异步方法中使用async void
,这就是async Task
的作用。前者只是为了允许与事件处理程序兼容,我假设情况并非如此。
- 如果
Do1()
和Do2()
彼此独立,则应该分别运行它们。如果它们是长时间运行/阻塞的进程,则这一点更为重要 - 另一方面,如果它们是相关的,并且第一个线程执行另一个线程所需的一些操作,那么最好在一个线程中运行它们,以减少线程开销。毕竟,你事先就知道它们需要按顺序运行