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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:19:09