要理解这个问题,请查看await
调用以及以下示例的函数InitSyncContext()
的定义。
基于此我想知道程序将如何在每个场景中表现,因为我不完全理解调用await InitSyncContext(store)
和在没有返回的情况下调用await
之间的区别Task
。
作为参考,我之前做了一项研究,我发现了一个类似的example here,但我认为这与我的情况有所不同。
*以下代码是真实世界代码的简化示例,仅用于演示目的。
void Main()
{
Initializer();
}
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
InitFileSync(store);
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
//------------- Second Method -------------
void Main()
{
Initializer();
}
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
InitFileSync(store);
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
答案 0 :(得分:4)
等待异步任务函数和在void函数内调用await之间的区别是什么?
阅读Stephen Cleary先生的精美文章 Async/Await - Best Practices in Asynchronous Programming ,这可能是一个非常大的问题。
一些摘要点:
避免异步void - 优先于async void方法的异步任务方法
答案 1 :(得分:3)
在
async Task
函数中等待await
函数和调用void
之间的区别是什么?
全世界!一切......然后是一些。让我们退后一步,从一些基础知识开始。
你应该一直&#34;异步#34;,即;如果您要返回等待(Task
或Task<T>
),则应正确使用async
和await
个关键字。
这里有几件事需要澄清。您不应该有async void
个方法,而应该有async Task
- 例外是事件处理程序(其中委托被预定义为非任务返回)等等。让我们检查并挑选方法一(我将忽略Main
入口点):
<强>一强>
private async void Initializer()
{
var store = InitLocalStore();
await InitSyncContext(store); // <-- Here, await call
...
}
// Here returns Task (without having a return inside. No compile errors)
private async Task InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
您有一个Initializer
方法,它立即代码为async void
。这应该是async Task
,它应该有&#34; Async&#34;后缀。此外,您有InitSyncContext
接受store
变量并调用一些客户端初始化工作。这里的代码味道是您使用async
和await
。这不需要像这样的简单(单任务)工作负载。相反,您应该只使用return
关键字。最底层的例子。让我们看一下方法二:
<强>两个强>
private void Initializer()
{
var store = InitLocalStore();
InitSyncContext(store); // <-- Here without await call
...
}
// Here is void but with a async call inside
private async void InitSyncContext(MobileServiceSQLiteStore store)
{
await Client.SyncContext.InitializeAsync(store);
}
事情正式变得越来越糟糕!由于对异步命名法的误解,我们假设由于一种方法似乎可以正常工作&#34; ok&#34;没有考虑另一种方法可能效仿的最佳实践。您制作了InitSyncContext
方法async void
。方法不应该是async void
的原因是它们是永远不会发生的。内部异步状态机没有Task
锁定,因此状态丢失。当您删除来电者await
时,您说要启动此异步操作,但您不关心它的结果。
以下是实现所需功能的正确方法:
<强>正确强>
private async Task InitializerAsync()
{
var store = InitLocalStore();
await InitSyncContextAsync(store);
...
}
// Simply return the task that represents the async operation and let the caller await it
private Task InitSyncContextAsync(MobileServiceSQLiteStore store)
{
return Client.SyncContext.InitializeAsync(store);
}
关于代码段Main
方法的说明,如果这是控制台应用程序的一部分 - 进入异步堆栈的顶级入口点将调用.Result
或{{ 1}}。
进一步阅读
答案 2 :(得分:-1)
在第一个示例中,编译器生成如下内容:
TheadPool.RunTask(()=>InitSyncContext(store)).ContinueWith(()=>InitFileSync(store))
第二 - 没有什么有趣的。因为没有人等到任务结束。所有调用都将在主线程exept中等待Client.SyncContext.InitializeAsync(store);