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

控制台应用中如何从子线程调用主线程执行方法?

控制台应用中子线程调用主线程方法的解决方案

控制台应用程序默认没有内置的SynchronizationContext,所以你原来的代码会因为context为空而抛出异常。下面提供两种实用的实现方式:

方法一:基于线程安全队列的任务调度

主线程维护一个线程安全的任务队列,子线程将需要在主线程执行的方法加入队列,主线程循环处理队列中的任务。

using System;
using System.Collections.Concurrent;
using System.Threading;

class Program
{
    // 线程安全的任务队列,存储需要主线程执行的委托
    private static readonly ConcurrentQueue<Action> _mainThreadTasks = new ConcurrentQueue<Action>();
    // 通知主线程有新任务的信号
    private static readonly AutoResetEvent _taskSignal = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Thread t = new Thread(Worker);
        t.Start();

        // 主线程循环处理任务
        while (true)
        {
            // 等待任务信号,超时时间设为100ms避免卡死
            if (_taskSignal.WaitOne(100))
            {
                while (_mainThreadTasks.TryDequeue(out Action task))
                {
                    task.Invoke();
                }
            }

            // 子线程结束后退出循环,处理剩余任务
            if (!t.IsAlive)
            {
                while (_mainThreadTasks.TryDequeue(out Action task))
                {
                    task.Invoke();
                }
                break;
            }
        }
    }

    static void Worker()
    {
        Console.WriteLine($"子线程ID: {Thread.CurrentThread.ManagedThreadId}");
        // 将需要主线程执行的方法加入队列
        _mainThreadTasks.Enqueue(() => HelloWorker());
        // 通知主线程有新任务
        _taskSignal.Set();

        // 模拟子线程工作
        Thread.Sleep(1000);
    }

    static void HelloWorker()
    {
        Console.WriteLine($"Hello from the main thread! Thread ID: {Thread.CurrentThread.ManagedThreadId}");
    }
}

方法二:使用TaskCompletionSource实现单次调用

如果只需要子线程触发主线程执行一次方法,可以用TaskCompletionSource让主线程等待子线程的请求,再执行目标方法。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
        Action mainThreadAction = null;

        Thread t = new Thread(() => Worker(ref mainThreadAction, tcs));
        t.Start();

        // 主线程等待子线程传递执行方法
        tcs.Task.Wait();
        // 执行主线程方法
        mainThreadAction?.Invoke();
    }

    static void Worker(ref Action mainThreadAction, TaskCompletionSource<bool> tcs)
    {
        Console.WriteLine($"子线程ID: {Thread.CurrentThread.ManagedThreadId}");
        // 给主线程赋值需要执行的方法
        mainThreadAction = HelloWorker;
        // 通知主线程可以执行了
        tcs.SetResult(true);

        // 模拟子线程工作
        Thread.Sleep(1000);
    }

    static void HelloWorker()
    {
        Console.WriteLine($"Hello from the main thread! Thread ID: {Thread.CurrentThread.ManagedThreadId}");
    }
}

关键说明

  • 控制台应用没有UI线程那种内置的消息循环,必须自己实现任务调度逻辑
  • 第一种方法适合多次调用场景,主线程可持续处理子线程提交的任务
  • 第二种方法适合单次/少量调用场景,逻辑更简洁

内容的提问来源于stack exchange,提问作者Pavel Vlasák

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 15:52:18