树莓派温控C#程序出现内存泄漏崩溃问题排查求助
问题根因排查
1. 多余的TempHumidity实例创建
你在两处存在完全不必要的实例创建操作,平白增加内存分配开销:
- Main函数每次循环都重新创建
TempHumidity实例,用完再设为null,完全可以复用同一个实例 RefreshSensorData方法内部又额外new了一个TempHumidity实例来调用GetPinData,直接用当前实例的this.GetPinData即可,根本不需要新建实例
2. Dht11实例频繁创建销毁
你每次读取每个引脚的传感器数据时,都会重新new一个Dht11实例,虽然用了using语法触发Dispose,但Iot.Device.DHTxx库在Linux ARM平台(树莓派)上,频繁创建销毁DHT实例时存在已知的底层资源泄漏问题,包括GPIO句柄、非托管内存没有被正确释放,这是你内存持续上涨的核心原因。
3. 不必要的手动GC调用
你手动调用GC.Collect()的操作不仅不会帮助回收内存,反而会打乱.NET GC的默认回收策略,将短生命周期对象提升到更高回收代,推迟回收时间,加剧内存堆积。
4. 采样频率不合理
DHT11传感器的硬件采样上限是1次/秒,你设置的500ms读一次不仅读不到有效新数据,还会加倍产生无用的资源开销。
修复方案
1. 复用实例减少不必要分配
修改Main函数逻辑,全局复用同一个TempHumidity实例:
// 循环外只创建一次实例 var TH = new TempHumidity(); while (true) { TH.RefreshSensorData(); Thread.Sleep(1000); // 调整为1秒采样一次,符合DHT11硬件规格 }
修改RefreshSensorData方法,删除多余的实例创建:
public void RefreshSensorData() { int[] pins = new int[] { 10, 9, 11, 5, 6, 13, 19, 26 }; foreach (var pin in pins) { try { this.GetPinData(pin); // 直接调用当前实例的方法 } catch (Exception e) { Console.WriteLine(e); } } }
2. 复用Dht11实例避免频繁创建
在TempHumidity类中增加字典缓存所有引脚的Dht11实例,全局复用:
public class TempHumidity { public static List<Sensor> SensorData = new List<Sensor>(); // 新增Dht11实例缓存 private Dictionary<int, Dht11> _dhtCache = new Dictionary<int, Dht11>(); private void GetPinData(int pin) { // 优先从缓存取实例,不存在再创建 if (!_dhtCache.TryGetValue(pin, out Dht11 dht)) { dht = new Dht11(pin); _dhtCache.Add(pin, dht); } // 删掉原来的using块,不再每次销毁实例 double testVal = dht.Temperature.DegreesFahrenheit; // 后面的原有业务逻辑保持不变即可 // ... } // 程序退出时统一释放所有Dht11实例 public void DisposeSensors() { foreach (var dht in _dhtCache.Values) { dht.Dispose(); } _dhtCache.Clear(); } }
3. 升级依赖包
将Iot.Device.DHTxx的NuGet包升级到最新稳定版,官方已修复部分历史版本的内存泄漏问题。
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

