如何在C#多线程中实现Thread1向Thread2传递数据?
线程间传递数据的几种实现方案
嗨,这个问题在多线程编程里太常见了!你的核心需求是让Thread1完成任务后把数据交给Thread2,首先得解决两个关键点:让数据能被两个线程访问到,以及确保Thread2在数据准备好之后再去读取(不然可能拿到空值或者未完成的内容)。另外还要注意线程安全,避免多线程同时操作共享数据出问题。
咱们先看看你的原代码问题:newstring是thread1方法里的局部变量,thread2根本访问不到它,而且你同时启动两个线程,thread2大概率会在thread1还没生成数据的时候就执行Console.WriteLine,肯定拿不到想要的结果。下面给你几种实用的解决方案:
方案一:共享变量+同步事件(基础版)
把数据定义为类级别的共享字段,再用ManualResetEvent来通知Thread2数据已准备好,这样Thread2不用轮询,效率更高。
using System; using System.Threading; class Program { // 类级别的共享变量,让两个线程都能访问 private static string _sharedResult; // 同步事件:用于通知Thread2数据已准备完成 private static ManualResetEvent _dataIsReady = new ManualResetEvent(false); static void Main(string[] args) { Thread t1 = new Thread(Thread1Work); t1.Start(); Thread t2 = new Thread(Thread2Work); t2.Start(); // 等待两个线程都完成(可选,根据你的业务需求) t1.Join(); t2.Join(); } static void Thread1Work() { // 模拟Thread1的耗时工作 Thread.Sleep(1000); _sharedResult = "123"; // 通知Thread2:数据准备好了! _dataIsReady.Set(); } static void Thread2Work() { // 在这里等待,直到Thread1发出数据准备好的信号 _dataIsReady.WaitOne(); // 现在可以安全读取共享数据了 Console.WriteLine(_sharedResult); // 如果需要重复使用这个事件,用完后重置状态 _dataIsReady.Reset(); } }
如果你的数据是复杂对象,记得加lock来保证线程安全,比如:
private static readonly object _lockObj = new object(); // 在Thread1里赋值时 lock(_lockObj) { _sharedResult = 你的复杂对象; } // 在Thread2里读取时 lock(_lockObj) { var data = _sharedResult; }
方案二:使用Task(推荐,更简洁灵活)
.NET里的Task比直接用Thread更现代化,支持延续任务,能自动处理线程同步,代码更简洁。
using System; using System.Threading.Tasks; class Program { static void Main(string[] args) { // 启动Task1,完成后返回结果 Task<string> task1 = Task.Run(() => { // 模拟耗时工作 Task.Delay(1000).Wait(); return "123"; }); // 给Task1添加延续任务:Task1完成后自动执行Task2的逻辑 Task task2 = task1.ContinueWith(prevTask => { // 直接从prevTask.Result获取Task1的结果 string data = prevTask.Result; Console.WriteLine(data); }); // 等待所有任务完成 Task.WaitAll(task2); } }
这种方式不需要手动管理同步事件,.NET框架会帮你处理线程调度和结果传递,非常省心。
方案三:生产者-消费者模式(适合持续产生/处理数据)
如果Thread1是持续产生数据,Thread2需要持续处理这些数据,用BlockingCollection是最佳选择——它自带线程安全,不用手动加锁,还能自动阻塞等待新数据。
using System; using System.Collections.Concurrent; using System.Threading; class Program { // 线程安全的阻塞队列 private static BlockingCollection<string> _dataQueue = new BlockingCollection<string>(); static void Main(string[] args) { Thread producerThread = new Thread(Producer); Thread consumerThread = new Thread(Consumer); producerThread.Start(); consumerThread.Start(); // 等待生产者完成工作 producerThread.Join(); // 告诉消费者:不会再有新数据了 _dataQueue.CompleteAdding(); // 等待消费者处理完所有数据 consumerThread.Join(); } static void Producer() { // 模拟多次产生数据 Thread.Sleep(1000); _dataQueue.Add("123"); Thread.Sleep(500); _dataQueue.Add("456"); Thread.Sleep(300); _dataQueue.Add("789"); } static void Consumer() { // 持续读取队列中的数据,直到队列被标记为"完成添加" foreach (string data in _dataQueue.GetConsumingEnumerable()) { Console.WriteLine("收到数据:" + data); } } }
以上几种方案可以根据你的实际场景选择:如果只是单次传递数据,方案一或方案二就够了;如果是持续的生产-消费,方案三更合适。
内容的提问来源于stack exchange,提问作者P. Dock
相关产品推荐
相关产品推荐

