我想知道什么是调用嵌套异步方法的最佳方法,如果我想要两个方法都是异步的。
首先:来电方法必须返回Task
public async Task SaveChangesAsync()
{
await Context.SaveChangesAsync();
}
public Task UpdateAsync(List<TEntity> entities)
{
foreach (TEntity entity in entities)
{
BeforeUpdate(entity);
Context.Entry(entity).State = EntityState.Modified;
}
return SaveChangesAsync();
}
第二:来电方法必须有async - await
,方法为
public async Task SaveChangesAsync()
{
await Context.SaveChangesAsync();
}
public async Task UpdateAsync(List<TEntity> entities)
{
foreach (TEntity entity in entities)
{
BeforeUpdate(entity);
Context.Entry(entity).State = EntityState.Modified;
}
await SaveChangesAsync();
}
答案 0 :(得分:4)
此代码不应使用async/await
,除非这些方法中有部分内容未显示。
换句话说,这就是这些方法的编写方式:
public Task SaveChangesAsync()
{
return Context.SaveChangesAsync();
}
public Task UpdateAsync(List<TEntity> entities)
{
foreach (TEntity entity in entities)
{
BeforeUpdate(entity);
Context.Entry(entity).State = EntityState.Modified;
}
return SaveChangesAsync();
}
这基本上是你没有展示的选项3,根本没有async/await
的痕迹。
原因是代码的执行方式如下:
UpdateAsync
的所有部分,这意味着foreach
- 循环将在调用线程上执行SaveChangesAsync()
的调用,直到它返回,仍在调用线程SaveChangesAsync
会调用Context.SaveChangesAsync()
直到它返回,仍然在调用线程简而言之,这些方法的所有工作已经在调用线程上完成,剩下的就是仅 Context.SaveChangesAsync
的async-ness 。如果你完全删除async/await
并简单地返回将async-ness包装回来的任务,你就没有牺牲任何功能,但你已经删除了编译器为你生成的所有复杂性{{1方法。
一般规则如下:
除非您需要在 之后执行异步方法,否则请不要使用
async/await
由于您的方法在调用异步方法后立即结束,因此您最好只返回相关任务,而不是使用async/await
。
答案 1 :(得分:3)
await
可以适用于任何Task
。它不一定是async
方法的结果。事实上,它根本不是任何方法的结果。
那就是说,我建议任何包含非平凡逻辑的方法都应该使用async
/ await
:
public async Task UpdateAsync(List<TEntity> entities)
{
foreach (TEntity entity in entities)
{
BeforeUpdate(entity);
Context.Entry(entity).State = EntityState.Modified;
}
await SaveChangesAsync();
}
这是因为async
捕获了方法体中的异常,并将它们放在返回的Task
上,这是调用任务返回方法时的预期行为。如果您在此处忽略async
/ await
,那么BeforeUpdate
或设置State
的任何例外情况都会被直接抛出而不是放在Task
上。
另一方面,您的调用方法很简单,因此您可以在那里忽略async
/ await
:
public Task SaveChangesAsync()
{
return Context.SaveChangesAsync();
}
答案 2 :(得分:1)
当你进行异步时,需要通过调用堆栈使用await
和async
,否则代码将不会异步执行。因此,请在两种方法上使用async
。
如果异步方法不使用await运算符来标记暂停 一点,该方法作为同步方法执行,尽管如此 异步修饰符
答案 3 :(得分:1)
正确的方法是Async All the Way向下,这意味着你必须采取第二种方法!
第一种方法不能按预期工作,因为您没有与当前上下文同步而只返回task
。现在您的任务将在未来的某个时间完成,但由于您没有与当前同步上下文同步,因此您无法再次获得结果(甚至是任何异常)!