首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步和等待不按预期返回调用方

异步和等待不按预期返回调用方
EN

Stack Overflow用户
提问于 2013-10-07 19:04:52
回答 2查看 13.2K关注 0票数 3

我有一个简单的asyncawait示例,我正在努力完成,并且执行没有像我预期的那样返回给调用者。下面是顶层方法:

代码语言:javascript
复制
protected async void MyDDL_SelectedIndexChanged(object sender, EventArgs e)
{
  Task longRunningTask = LongRunningOperationAsync();
  DoOtherStuff1();
  DoOtherStuff2();
  DoOtherStuff3();
  await longRunningTask;
}

下面是LongRunningOperationAsync方法,它不像预期的那样工作,并且同步运行:

代码语言:javascript
复制
 private async Task LongRunningOperationAsync()
 {
   var myValues = await GetStuffViaLongRunningTask();
   //Code to work with myValues here...
 }

以下是GetStuffViaLongRunningTask的定义

代码语言:javascript
复制
private async Task<IList<MyClass>> GetStuffViaLongRunningTask()
{

    //...Calls to get and build up IList<MyClass>
    return results;

}

问题是上面的代码做了,而不是,返回给调用者,并开始像我预期的那样运行DoOtherStuff1();方法。但是,与调用我自己的方法并将其替换为对await Task.Delay(10000);的调用(如所有简单示例所示)不同,代码的工作方式与预期的一样:

代码语言:javascript
复制
 private async Task LongRunningOperationAsync()
 {
   //Returns to caller as expected:
   await Task.Delay(10000);
 }

使用上述代码的调用方具有longRunningTask,其状态为WaitingForActivation,而不是RanToCompletion,这表明它仍在处理中。

您可能会说我的GetStuffViaLongRunningTask()方法运行得如此之快,而我只是看不到结果。然而,它总是在3-7秒之间运行,当调试时,您可以知道调用是阻塞的和同步的。

我在这里做错了什么,这样我对LongRunningOperationAsync()的调用就不会在到达await单词以调用该方法中的LongRunningOperationAsync时异步工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-07 19:20:56

假设//...Calls to get and build up IList<MyClass>是同步的CPU绑定工作,那么问题是,在GetStuffViaLongRunningTask结束或到达其第一个await调用之前,它不会返回。您应该得到关于该方法的编译器警告,因为它是一个没有awaitawait方法。

相反,方法不应该是async,而是向调用方清楚地表明它是同步工作的。只需将签名调整为:

代码语言:javascript
复制
private IList<MyClass> GetStuffViaLongRunningTask()

然后,在调用它时,使用Task.Run确保长时间运行的CPU绑定工作在另一个线程中完成:

代码语言:javascript
复制
private async Task LongRunningOperationAsync()
{
    var myValues = await Task.Run(() => GetStuffViaLongRunningTask());
    //Code to work with myValues here...
}
票数 3
EN

Stack Overflow用户

发布于 2013-10-07 19:22:20

//...Calls to get and build up IList<MyClass>

你得告诉我们正在打哪些电话。如果您想在这个结构中使用异步/等待,那么您需要进行异步调用。

如果您的GetStuffViaLongRunningTask函数没有执行异步调用,那么您可以启动一个新任务,如下所示:

代码语言:javascript
复制
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;
    });
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19232575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档