何时应等待任务?

8

假设我有一个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中等待它?我像示例中那样等待会对我的应用程序产生负面影响吗?

2个回答

4
这是否意味着我可以在CreateAsync中返回Task而不用等待,然后在Get中最终等待它?
是的,你可以这样做,实际上更有效率。如果按照你目前的方式使用await,每个异步方法都会生成一个状态机,这意味着更多的代码和上下文切换。
这样做会对我的应用程序产生负面影响吗?
由于状态机和上下文切换,会有轻微的性能惩罚。成本通常比调用成本低得多,但最终总会累加起来。关于这个主题,异步性能:了解异步和等待的成本是一篇很好的文章。
正如@Richard Szalay指出的那样,请确保最终等待任务,否则任何发生的异常都将无法观察并被忽略。

值得注意的是,如果返回一个未等待的任务,其缺点在于,如果抛出异常,则该方法不会在异步调用堆栈中。 - Richard Szalay
好的观点,但他确实说他最终在“Get”方法中等待它,所以异常将被抛出,但我会明确指出这一点。 - NeddySpaghetti
异常不会被吞掉,但是没有等待的方法不会出现在异步调用堆栈上(这可能会使调试变得更加困难)。 - Richard Szalay

0

async和await用于在需要异步运行方法时使用。 没有await的async是同步的。

async方法返回任务或void await等待任务完成

因此,在返回任务的方法之前使用await

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

以此类推。

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

如果您需要更多澄清,请告诉我。


我非常确定 OP 知道 await/asyn 的作用。他的问题更像是:“我应该使用多个 awaits 还是单个 await” - Jürgen Steinblock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接