我有一个简单的async
和await
示例,我正在努力完成并且执行没有按照我的预期返回到调用者。这是顶级方法:
protected async void MyDDL_SelectedIndexChanged(object sender, EventArgs e)
{
Task longRunningTask = LongRunningOperationAsync();
DoOtherStuff1();
DoOtherStuff2();
DoOtherStuff3();
await longRunningTask;
}
以下是LongRunningOperationAsync
方法无法按预期工作并同步运行:
private async Task LongRunningOperationAsync()
{
var myValues = await GetStuffViaLongRunningTask();
//Code to work with myValues here...
}
以下是GetStuffViaLongRunningTask
private async Task<IList<MyClass>> GetStuffViaLongRunningTask()
{
//...Calls to get and build up IList<MyClass>
return results;
}
问题是上面的代码不返回调用方并开始运行DoOtherStuff1();
方法,正如我所料。但是,不是调用我自己的方法并将其替换为await Task.Delay(10000);
调用,就像所有简单示例所示, 代码按预期工作:
private async Task LongRunningOperationAsync()
{
//Returns to caller as expected:
await Task.Delay(10000);
}
使用上述代码的来电者longRunningTask
的状态为WaitingForActivation
,而不是RanToCompletion
,表明它仍在处理中。
您可能会说我的GetStuffViaLongRunningTask()
方法运行得太快,我看不到结果。但是,它总是需要3-7秒才能运行,您可以在调试时判断调用是否阻塞并且同步。
我在这里做错了什么,所以当我到达LongRunningOperationAsync()
字以便在该方法中调用await
时,我对LongRunningOperationAsync
的调用是不是异步工作?
答案 0 :(得分:4)
假设//...Calls to get and build up IList<MyClass>
是同步CPU绑定工作,问题是GetStuffViaLongRunningTask
在它结束或点击其第一个await
调用之前不会返回。您应该在该方法上收到编译器警告,因为它是async
方法,其中没有await
。
相反,该方法不应该是async
,以清楚地向其调用者表明它是同步工作。只需将签名调整为:
private IList<MyClass> GetStuffViaLongRunningTask()
然后在调用它时使用Task.Run
来确保在另一个线程中完成长时间运行的CPU绑定工作:
private async Task LongRunningOperationAsync()
{
var myValues = await Task.Run(() => GetStuffViaLongRunningTask());
//Code to work with myValues here...
}
答案 1 :(得分:1)
//...Calls to get and build up IList<MyClass>
您需要告诉我们正在进行哪些通话。如果要对此结构使用async / await,则需要进行异步调用。
如果您的GetStuffViaLongRunningTask
功能没有执行异步调用,那么您可以开始执行以下新任务:
private Task<IList<MyClass>> GetStuffViaLongRunningTask()
{
return Task.Factory.StartNew(() =>
{
//...Calls to get and build up IList<MyClass>
// You can make synchronous calls here
return list;
});
}