C#中是否可修改作为参数传递给其他线程的对象?
基础认知纠正
首先明确两个核心误区:
- 你这里创建的是同一进程内的工作线程,不是子进程。同一进程的所有线程共享进程的虚拟内存空间,不存在“线程被分配到其他内存空间”的说法。
- 示例代码修改不生效和线程机制无关,是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
相关产品推荐
相关产品推荐

