控制台应用中如何从子线程调用主线程执行方法?
控制台应用中子线程调用主线程方法的解决方案
控制台应用程序默认没有内置的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
相关产品推荐
相关产品推荐

