使用以下两种方法,自上而下的流程(其中top是API动作,down是Db事务)之间有什么区别。
完整的异步等待流程
async Task X()
{
await Y();
}
async Task Y()
{
await Z();
}
async Task Z()
{
await session.CommitAsync();
}
仅顶级方法使用async-await。
async Task X()
{
await Y();
}
Task Y()
{
Z();
return Task.CompletedTask;
}
Task Z()
{
session.CommitAsync();
return Task.CompletedTask;
}
当异步指示Y应该异步执行时,Z发生了什么?
答案 0 :(得分:2)
异步指示Y应该异步执行,
是错误的陈述。异步修饰符允许 Y等待某些事情,它不会强制执行任何异步操作。
只要something()
实际上正在执行异步操作,您的第一个代码段就可以了。
第二个根本不是异步的,它只是抛出一些async
和await
关键字,但是在这里并没有完成任何事情。
答案 1 :(得分:1)
编辑:问题已更改。以下是一般的异步答案
后面的Z
根本不会等待CommitAsync
才返回。这是一种失火的情况。
Task Z()
{
session.CommitAsync();
return Task.CompletedTask;
}
在api控制器的情况下,这意味着Web请求将在提交会话之前返回给客户端。
请注意,对于返回数据的方法,无法完成此操作。
第二个注意事项是,返回Task
并没有任何好处,返回类型可以更改为void
(这可能会或可能不会帮助您进行推理)。
原始答案,仍然有用
假设在ZRealAsync
中调用await db.(...).ToListAsync()
,在ZPretendAsync
中调用ToList()
,然后返回Task.CompletedTask
。
区别在于,将查询发送到数据库后,恰好调用ZRealAsync
的线程可用于执行其他操作,而调用ZPretendAsync
的线程将无法执行。用于其他任何事情,直到从数据库中获得结果,它都将等待;即使X
被标记为async
并使用await
。
如果您的网络控制器调用ZPretendAsync
,则即使X
被标记为async
并使用{ {1}}关键字。使用await
,n个线程可以处理n个以上的并发请求。 ZRealAsync
会带来真正的改变,但前提是它是真实的。