【问题标题】:Get result from async method从异步方法获取结果
【发布时间】:2014-01-19 23:58:08
【问题描述】:

我的服务中有这个方法:

public virtual async Task<User> FindByIdAsync(string userId)
{
    this.ThrowIfDisposed();
    if (userId == null)
    {
        throw new ArgumentNullException("userId");
    }
    return await this.repository.FindByIdAsync(userId);
}

然后在视图中我有这个代码:

using (var service = new UserService(new CompanyService(), User.Identity.GetUserId()))
{
    var user = service.FindByIdAsync(id);
}

但用户是Task,而不是User。我尝试将 await 添加到服务调用中,但我不能使用 await,除非当前方法是 async。 如何访问 User 类?

【问题讨论】:

  • 使当前方法异步并添加等待。
  • 你能显示service.FindByIdAsync(id)的代码吗?
  • 'async' 方法就像僵尸:它们传播。异步方法调用者必须是异步的。
  • 大声笑 :) 很好的描述

标签: c# entity-framework asynchronous


【解决方案1】:

正如 Bas Brekelmans 指出的那样,最好的解决方案是使调用方法 async 然后使用 await

当你创建一个方法async时,你应该改变返回类型(如果是void,把它改成Task;否则,把它从T改成Task&lt;T&gt;)并添加一个@ 987654330@ 方法名的后缀。如果返回类型不能Task,因为它是一个事件处理程序,那么您可以改用async void

如果调用方法是构造函数,你可以使用我博客中的one of these techniques。如果调用方法是一个属性getter,你可以使用我博客中的one of these techniques

【讨论】:

  • 说伙伴...你是.net框架的核心开发者吗?您深入参与了 c# 的并发开发
  • @IamStalker:哈哈,不。我不为微软工作。我只是在并发应用程序方面有很多经验,所以我了解它们的来源,尤其是async。有一个叫 Stephen Toub 的人,他在微软工作,并深入参与了 TPL、Dataflow 和 async
  • 斯蒂芬,我的问题是我的视图是虚拟的,所以它调用我的服务,但它不是一个函数,所以我不能预先异步:(还有其他解决方法吗?
  • 调用FindByIdAsync的代码必须在一个方法中...你为什么不能在async创建那个方法?
【解决方案2】:
  • async 方法中使用this 而不使用特殊的线程锁定对象是危险
  • 如果您不能使用await,请使用如下代码。

    Task<User> task = TaskFindByIdAsync();
    
    task.Wait(); //Blocks thread and waits until task is completed
    
    User resultUser = task.Result;
    

【讨论】:

  • 这是一个非常糟糕的做法。这可能是一个隐藏的僵局。 see this
  • @Olivier 看起来并不依赖于此。任务may cause a deadlock中只有不清楚的代码
  • 一个好习惯是在调用方法时不要依赖如何实现方法。如果 Wait() 在上下文线程上,并且方法 Waited(不是 A-waited)使用“await”,那么您将死锁(因为它等待主线程可用)。
  • 不清楚您所说的“在没有特殊线程锁定对象的异步方法中使用它是危险的”是什么意思。你能澄清一下吗?
  • 以“只读”方式(即读取字段)使用 'this 是非常安全的,甚至是多线程方式。我认为 OP 的代码不需要锁定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
相关资源
最近更新 更多