C#中定时器无法访问device对象,如何快速解决?
问题核心
你遇到的问题本质是作用域限制:device是按钮点击方法内的局部变量,OnTimedEvent方法不在该局部作用域中,因此无法直接访问这个变量;而按钮事件能正常运行,是因为它本身就在device的作用域范围内。
最简单的两种解决方法
方案1:用闭包捕获变量(最简便,无需修改类结构)
直接用Lambda表达式替代独立的OnTimedEvent方法,这样可以直接捕获局部的device变量,无需额外调整类结构:
private void Button_Start_Logging_FMS_Data_Click(object sender, EventArgs e) { try { var devices = PX409Usbh.DetectDevices().ToList(); if (devices.Count == 0) { MessageBox.Show("no devices found. Make sure the pressure sensor is connected"); return; } foreach (var d in devices) { d.Initialize(); } var device = devices[0]; string serialNumber = device.SerialNumber; string unitMeasurement = device.Units; double rawExternalPressure = device.ReadPressure(); // 用Lambda表达式绑定定时器事件,直接捕获device变量 System.Timers.Timer aTimer = new System.Timers.Timer(); aTimer.Elapsed += (source, eArgs) => { double timedPressure = device.ReadPressure(); // 这里可添加数据记录、UI更新等后续逻辑 }; aTimer.Interval = 1000; aTimer.Enabled = true; } catch (Exception ex) { Logging.Write_To_Log_File("Error", MethodBase.GetCurrentMethod().Name, "", "", ex.ToString(), "", "", "", 2); } }
方案2:将device提升为类字段(适合多方法复用场景)
如果后续有其他方法需要访问该设备对象,可以把device定义为类的成员变量,打破局部作用域限制:
// 在类的顶部定义成员变量(替换成实际的设备类型) private PX409Usbh.Device _device; private void Button_Start_Logging_FMS_Data_Click(object sender, EventArgs e) { try { var devices = PX409Usbh.DetectDevices().ToList(); if (devices.Count == 0) { MessageBox.Show("no devices found. Make sure the pressure sensor is connected"); return; } foreach (var d in devices) { d.Initialize(); } _device = devices[0]; string serialNumber = _device.SerialNumber; string unitMeasurement = _device.Units; double rawExternalPressure = _device.ReadPressure(); System.Timers.Timer aTimer = new System.Timers.Timer(); aTimer.Elapsed += OnTimedEvent; aTimer.Interval = 1000; aTimer.Enabled = true; } catch (Exception ex) { Logging.Write_To_Log_File("Error", MethodBase.GetCurrentMethod().Name, "", "", ex.ToString(), "", "", "", 2); } } private void OnTimedEvent(object source, ElapsedEventArgs e) { // 增加空值判断,避免未初始化就调用的异常 if (_device != null) { double timedPressure = _device.ReadPressure(); } }
注意事项
- 方案1的闭包会自动维持
device的引用,避免对象被GC回收,无需额外处理。 - 方案2建议始终添加空值判断,防止意外触发定时器时出现空引用异常。
内容的提问来源于stack exchange,提问作者user1438082
相关产品推荐
相关产品推荐

