【问题标题】:When should you await a Task?你应该什么时候等待一个任务?
【发布时间】:2015-05-30 12:10:37
【问题描述】:

假设我有一个Repository 类,它有一个DbContext。在这个类中,我有一个方法:

public async Task<T> CreateAsync(T obj)
{
    var o = _dbSet.Add(obj);
    await _dbContext.SaveChangesAsync();
    return o;
}

Service 类中,我使用此方法创建对象:

public async Task<MyObject> Create()
{
    return await _repository.CreateAsync(new MyObject());
}

最后在我的 api 控制器 MyObjectController 中,我像这样返回这个对象:

public async Task<IHttpActionResult> Get()
{
    return Ok(await _service.Create());
}

我对所有这些 asyncawait 关键字感到困惑。我知道Task 是可以等待的。这是否意味着我可以从CreateAsync 返回Task 而无需在CreateAsyncCreate 中等待,然后最终在Get 中等待它?像示例中那样执行等待是否会对我的应用程序产生负面影响?

【问题讨论】:

    标签: c# entity-framework asynchronous


    【解决方案1】:

    这是否意味着我可以只从 CreateAsync 返回任务,而无需在 CreateAsync 或 Create 中等待,然后最终在 Get 中等待它?

    是的,你可以这样做,它实际上更有效。如果你在等待的同时进行等待,每个异步方法都会生成一个状态机,这意味着更多的代码和更多的上下文切换

    像示例中那样执行等待是否会对我的应用程序产生负面影响?

    由于状态机和上下文切换,会有轻微的性能损失。费用通常远低于通话费用,但最终都会加起来。 Async Performance: Understanding the Costs of Async and Await 是一篇关于这个主题的好文章。

    正如@Richard Szalay 所指出的,只要确保你最终await 任务,否则发生的任何异常都将保持未被观察到并被吞没。

    【讨论】:

    • 值得注意的是,不等待就返回任务的缺点是,如果抛出异常,相关方法将不会在异步调用堆栈中
    • 好点,但他确实说他最终会在 Get 方法中等待它,所以异常会被抛出,但我会明确指出。
    • 异常不会被吞掉,但是没有等待的方法不会出现在异步调用堆栈上(这可能会使调试变得更加困难)
    【解决方案2】:

    当您希望方法异步运行时,使用 async 和 await。 没有等待的异步是同步的

    异步方法返回任务或无效 await 等待任务完成

    所以在返回任务的方法之前使用await

    您的 Get 方法正在等待完成您的 create() 任务,该任务等待完成 createAsync 任务

    等等。

    _dbContext.SaveChangesAsync() 是异步方法,所以需要aaawait,否则可能返回错误o

    如果您需要更多说明,请告诉我

    【讨论】:

    • 我很确定 OP 知道 await/asyn 的作用。他的问题更像是“我应该使用多个等待还是单个等待”
    猜你喜欢
    • 2023-04-07
    • 2019-01-28
    • 2019-10-28
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多