如何让C#中DoSomething非阻塞等待async void方法DoMore执行完成?
问题分析与解决方案
原代码问题
你当前的代码里,DoMore用了async void返回类型,这种类型仅适用于事件处理程序,普通异步方法用它会导致调用者(DoSomething)无法跟踪其执行状态——所以DoSomething会直接跳过等待,继续执行后续代码,就出现了不符合预期的输出顺序。
而且你尝试的方案里用Task.Run(() => DoMore())完全没必要,反而额外创建了线程,违背了你的需求。
正确实现代码
要实现非阻塞等待且不额外开线程,只需要调整异步方法的返回类型,并正确使用await:
public class Example { public async Task DoSomething() { Console.WriteLine("DoSomething Start:"); // 直接await DoMore,无需额外包裹Task.Run await DoMore(); Console.WriteLine("DoSomething End:"); } public async Task DoMore() { Console.WriteLine("DoMore Start:"); // 用Task.Delay替代Thread.Sleep+Task.Run,避免阻塞线程 await Task.Delay(1000); Console.WriteLine("DoMore End:"); } }
关键调整点
- 把
async void换成async Task:async Task是普通异步方法的标准返回类型,调用者可以通过await等待它执行完成,这是实现非阻塞等待的前提。 - 直接
await异步方法:DoMore本身就是异步方法,直接await它不会创建额外线程,只会让DoSomething暂停执行,直到DoMore完成后再继续,完全符合非阻塞的要求。 - 替换
Task.Run(() => Thread.Sleep(1000))为Task.Delay(1000):Thread.Sleep会阻塞线程,而Task.Delay是真正的异步等待,不需要占用线程资源,更契合异步编程的设计。
调用时,在异步上下文里直接用await new Example().DoSomething()即可,输出顺序会和你预期的一致:
DoSomething Start: DoMore Start: DoMore End: DoSomething End:
内容的提问来源于stack exchange,提问作者Yakir Shlezinger
相关产品推荐
相关产品推荐

