You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Async/Await回调行为疑问:为何t.Result会阻塞后续代码执行?

为什么Console.WriteLine(t.Result)会阻塞后续代码执行?

嘿,这个问题戳中了很多异步编程初学者容易混淆的点,其实核心原因很简单:Task.Result和Task.Wait()本质上是完全一样的同步阻塞操作,只是一个返回结果、一个无返回值而已!

先理清楚你的代码执行流程

假设你的代码结构大概是这样的:

static void Main()
{
    Task<string> t = GetUrlContentAsync();
    Console.WriteLine(t.Result); // 这里会阻塞
    Console.WriteLine("I am done");
}

static async Task<string> GetUrlContentAsync()
{
    HttpClient client = new HttpClient();
    Task<string> getStringTask = client.GetStringAsync("https://example.com");
    string urlContents = await getStringTask;
    return urlContents;
}

当Main方法执行到t.Result时,发生了这些事:

  1. 之前启动的GetUrlContentAsync任务确实在后台运行,甚至可能已经执行到await getStringTask这一步,让出了线程回到Main。
  2. 但**Result属性会强制当前线程(也就是Main线程)停下来,同步等待整个t任务完全执行完毕**——不管任务内部有没有await,只要你调用Result,当前线程就会被阻塞,直到拿到任务的返回值。
  3. 只有当t任务彻底完成、Result拿到结果后,Main线程才会继续执行下一行的Console.WriteLine("I am done")。

await和Result/Wait()的本质区别

你之所以困惑,是把异步等待和同步阻塞搞混了:

  • await是异步等待:它会释放当前线程,让线程去处理其他工作,等任务完成后再回调回来继续执行后续代码,全程不会阻塞线程。
  • Result/Wait()是同步阻塞:它们会直接“卡住”当前线程,什么都不做,直到任务结束,完全剥夺了线程的异步能力。

如果你想让"I am done"先执行

要实现你预期的“先回到Main执行I am done,再处理任务结果”,需要把Main改成异步方法(C# 7.1及以上支持),并且不要用Result,而是用await异步等待任务:

static async Task Main()
{
    Task<string> t = GetUrlContentAsync();
    // 先执行这行,不用等任务完成
    Console.WriteLine("I am done");
    // 异步等待任务结果,不会阻塞线程
    string result = await t;
    Console.WriteLine(result);
}

这样执行顺序就会是先输出I am done,等任务完成后再输出网址内容。

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:20:51