C#如何将ref修饰的int变量传入窗口 实现跨窗口修改控制线程循环退出
你遇到的核心问题:C# 中值类型的 ref 参数只能在当前方法的作用域内使用,无法存储为类的成员变量在后续其他方法(比如按钮点击、定时器回调)中使用,所以你原本直接传 ref int 的思路走不通,有两种成熟的实现方案:
方案1:用引用类型包装int值
值类型本身不保留引用,你可以把int封装到一个引用类型的包装类中,这样所有地方操作的都是同一个对象内的值,天然同步:
首先定义包装类:
public class IntWrapper { public int Value; }
修改原有业务代码:
// 原来的int stop替换为包装类实例 public IntWrapper stop = new IntWrapper { Value = 0 }; public void main() { Thread thrDoStuff = new Thread(()=> dostuff(stop)); testWindow window = new testWindow(stop); } public void dostuff(IntWrapper stop) { while (true) { // 跨线程读取用Volatile.Read保证拿到最新值,避免CPU缓存导致的读取延迟 if (Volatile.Read(ref stop.Value) != 0) { break; } } // 退出循环后的其他逻辑 }
修改窗口代码:
public readonly DispatcherTimer Start = new DispatcherTimer(); // 类成员存储包装类实例 private IntWrapper _stop; public testWindow (IntWrapper stop ) { InitializeComponent(); _stop = stop; Start.Interval = TimeSpan.FromMilliseconds(100); Start.Tick += workloop; Start.IsEnabled = true; } private void buttonClick(object sender, RoutedEventArgs e) { // 直接修改包装类的Value属性,同步到所有引用位置 Volatile.Write(ref _stop.Value, 1); } private void workloop(object sender, EventArgs e) { Start.IsEnabled = false; Volatile.Write(ref _stop.Value, 1); }
注:Volatile 类属于 System.Threading 命名空间,需要提前引入
方案2:使用.NET原生的CancellationTokenSource(更推荐)
.NET 专门提供了 CancellationTokenSource 用于多线程/任务的取消场景,是官方推荐的标准实现,不需要自己处理内存可见性等问题:
修改原有业务代码:
public CancellationTokenSource cts = new CancellationTokenSource(); public void main() { Thread thrDoStuff = new Thread(()=> dostuff(cts.Token)); testWindow window = new testWindow(cts); } public void dostuff(CancellationToken token) { while (true) { if (token.IsCancellationRequested) { break; } } // 用完记得释放资源 cts.Dispose(); }
修改窗口代码:
public readonly DispatcherTimer Start = new DispatcherTimer(); private CancellationTokenSource _cts; public testWindow (CancellationTokenSource cts ) { InitializeComponent(); _cts = cts; Start.Interval = TimeSpan.FromMilliseconds(100); Start.Tick += workloop; Start.IsEnabled = true; } private void buttonClick(object sender, RoutedEventArgs e) { // 调用Cancel方法即可触发所有持有Token的位置收到取消通知 _cts.Cancel(); } private void workloop(object sender, EventArgs e) { Start.IsEnabled = false; _cts.Cancel(); }
内容的提问来源于stack exchange,提问作者superleo1000
相关产品推荐
相关产品推荐

