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

C#中是否可修改作为参数传递给其他线程的对象?

基础认知纠正

首先明确两个核心误区:

  1. 你这里创建的是同一进程内的工作线程,不是子进程。同一进程的所有线程共享进程的虚拟内存空间,不存在“线程被分配到其他内存空间”的说法。
  2. 示例代码修改不生效和线程机制无关,是C#的值类型传递规则导致的:int是值类型,调用thread.Start(year)时会先对int值做装箱操作,相当于把值拷贝了一份放到堆上的object对象里,method方法里修改形参p的指向,只会改当前方法栈里的形参副本,完全不会影响主线程里的year变量。

实现跨线程修改变量的可行方案

方案1:用引用类型包装值类型

引用类型传递的是堆上对象的引用,多个线程拿到的是同一个对象的引用,修改对象的属性就能全局生效。
示例代码:

class Program
{
    // 自定义引用类型包装值
    class ValueWrapper
    {
        public int Year { get; set; }
    }

    static void Main(string[] args)
    {
        Program o = new Program();
        ValueWrapper wrapper = new ValueWrapper { Year = 2021 };

        Thread thread = new Thread(new ParameterizedThreadStart(o.method));
        thread.Start(wrapper);

        while (true)
        {
            Console.WriteLine(wrapper.Year);
            Thread.Sleep(1000);
        }
    }

    public void method(object p)
    {
        Thread.Sleep(5000);
        // 直接修改引用对象的属性
        ((ValueWrapper)p).Year = 1500;
    }
}

运行后前5秒输出2021,5秒后输出会变成1500。

方案2:使用闭包捕获变量

如果不想额外定义包装类,可以用lambda表达式直接捕获外部变量,编译器会自动生成隐式的包装类,效果和方案1一致:

class Program
{
    static void Main(string[] args)
    {
        int year = 2021;

        // 用lambda捕获year变量
        Thread thread = new Thread(() =>
        {
            Thread.Sleep(5000);
            year = 1500;
        });
        thread.Start();

        while (true)
        {
            Console.WriteLine(year);
            Thread.Sleep(1000);
        }
    }
}

注意事项

多线程同时读写共享变量时会存在竞态条件,建议根据场景加锁或者使用Interlocked类提供的原子操作,避免出现不可预期的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:36:05