我有一个从数据库中获取数据的异步方法:
private async Task getDataAsync()
{
await getDataFromDatabaseAsync();
}
我有一个使用此方法的构造函数,以这种方式:
public MyViewModel()
{
Task.WhenAll(getDataAsync());
//getDataAsync().ConfigureAwait(false);
//next line of code
}
避免应用程序的唯一方法是不使用两个选项,两者似乎都运行正常。我可以使用WhenAll或者我可以使用ConfigureAwait(false)。
它在一个任务中调用方法getDataASync()的另一个选项,但我想这是一个更糟糕的选择,因为它需要更多的资源。
所以我想知道WhenAll和ConfigureAwait之间的区别。
当我以这种方式使用WhenAll时,代码行"下一行代码"在async方法完成后运行,还是在完成之前运行?
感谢。
答案 0 :(得分:1)
有一种常见的误解,即当你创建一个方法async
时,它实际上是异步执行的(即在一个单独的线程上)。事实并非如此:async
和await
是一种同步已经作为非同步代码的方法。如果您没有在单独的线程上执行任何操作,则async
代码将完全同步到最后。
由于getDataAsync
在与MyViewModel
构造函数相同的线程上执行,因此您可能会遇到死锁,因为线程会自行等待。当您使用ConfigureAwait
时,可以避免这种情况。
你是否应该这样做是一个不同的问题。你实际使用ConfigureAwait
做的是启动任务并允许await继续在一个单独的上下文(可以在一个单独的线程上)。除了你甚至不在这里使用await
之外,当你想在await之后执行UI操作时,在不同的上下文中继续可能会成为一个问题。
如果您想确保在构造函数中等待getDataAsync
,可以使用Task.Run
强制在线程池中执行:
var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();
Task.Run
和Wait()
之间执行的所有操作都可以在执行getDataAsync
期间运行。并行性在这里是否值得,取决于你在Wait()
之前做了什么。
您在MyViewModel
构造函数中所做的是最终同步所有异步操作并使构造函数的执行同步。如果要异步运行该操作,则需要启动另一个任务来执行此操作。所以你应该确定超过这一点async
不再需要了。如果是,则在另一个async
方法await getDataAsync()
上运行初始化,并在调用链的某个位置同步。