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

C# .NET6中线程内使用await导致线程中断的问题

问题分析:自定义线程内用await后后续代码没执行

问题说明

在.NET 6无Main函数的新式控制台应用里,自定义线程里的异步函数走到await那一行时,线程直接提前结束,[3]段代码完全没执行,实际跑出来的顺序是[1][2][4],和预期的[1][2][3][4]对不上。

测试代码

public class Question {
    public static async Task<double> testTask() {
        // [2]
        await Task.Run(() => {
            Console.WriteLine("start testTask {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < 100; i++) {
                Task.Delay(10).Wait();
            }
            Console.WriteLine("end testTask {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        });

        return 42.00;
    }

    static async Task ThreadFunction() {
        Console.WriteLine("ThreadFunction begin tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        // [1]
        //double x = await test.testTask().ConfigureAwait(true);
        double x = await test.testTask();

        int inserted = 0;
        for (long i = 0; i < 100; i++)
            System.Threading.Thread.Sleep(100);

        // [3]
        Console.WriteLine("ThreadFunction end tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
    }

    public static void startTestThread() {
        Console.WriteLine("start startTestThread. tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        Thread TestThread = new Thread(() => ThreadFunction());
        TestThread.Start();
        TestThread.Join();
        // [4]
        Console.WriteLine("end startTestThread. tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
    }
}

为啥会这样

  1. Thread不兼容异步方法:Thread的启动委托是无返回值的同步类型,你把async Task的ThreadFunction塞进去,相当于把它当成async void来执行——完全忽略了它返回的Task,根本不会等异步方法做完。
  2. 异步方法的提前返回特性:异步方法碰到第一个还没完成的await时,会立刻返回一个未完成的Task,然后让出当前线程。Thread看到委托执行到返回这一步,就认为任务完成了,直接把TestThread给终止了。
  3. 进程终止导致后续代码没机会跑:await之后的[3]段代码,本来会被调度到线程池的某个线程上继续执行,但主线程已经通过TestThread.Join()等完了TestThread,接着就执行[4]然后结束整个进程,线程池的代码还没来得及执行,进程就没了,所以[3]根本跑不起来。

怎么改

  • 别用Thread跑异步方法,改用Task.Run配合await来等待任务完成(这是异步编程的正确姿势):
    public static async Task startTestThread() {
        Console.WriteLine("start startTestThread. tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
        await Task.Run(() => ThreadFunction());
        Console.WriteLine("end startTestThread. tid={0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
    }
    
  • 要是非得用Thread,那就得同步等待异步方法完成(不推荐,会阻塞线程,失去异步的意义):
    Thread TestThread = new Thread(() => ThreadFunction().GetAwaiter().GetResult());
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:35:44