在C#开发中,你是否遇到过这些烦人的问题:程序运行一段时间后越来越卡?文件句柄泄露导致系统崩溃?数据库连接池耗尽?这些问题的根源往往是资源管理不当!
今天我们通过一个完整的工业设备监控系统案例,深入剖析IDisposable接口的正确使用方法。这不是枯燥的理论讲解,而是一个可以直接运行的实战项目,涵盖了文件操作、异步任务管理、事件处理等多个核心场景。
本文将解决的核心问题:如何在复杂的业务场景中正确实现资源的自动释放,避免内存泄露和性能问题。
在实际开发中,以下资源如果不正确释放,就会造成严重问题:
关键问题:.NET的垃圾回收器(GC)只能处理托管内存,对于非托管资源无能为力!
C#// ❌ 错误示例:不释放资源
public class BadExample
{
public void ProcessFile()
{
var writer = new StreamWriter("data.txt");
writer.WriteLine("Some data");
// 忘记调用writer.Dispose()
// 文件句柄将一直占用,直到GC回收(时机不确定)
}
}
这种写法在高并发场景下,很快就会耗尽系统资源!
C#public class StandardDisposable : IDisposable
{
private bool _disposed = false;
private FileStream _fileStream; // 非托管资源
private List<string> _data; // 托管资源
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // 告诉GC不需要调用析构函数
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 释放托管资源
_data?.Clear();
_fileStream?.Dispose();
}
// 释放非托管资源
// 例如:释放Win32 API句柄
_disposed = true;
}
}
// 析构函数(终结器)
~StandardDisposable()
{
Dispose(false);
}
}
核心要点:
Dispose(bool disposing)
是关键方法disposing=true
时释放所有资源disposing=false
时只释放非托管资源_disposed
标志避免重复释放让我们通过一个完整的工业监控系统来实践IDisposable模式:
C#// 系统架构
ConnectionManager (主管理器)
├── IndustrialDevice[] (多个设备)
│ ├── 数据监控任务
│ └── 取消令牌管理
└── DataLogger (数据记录器)
├── 文件流管理
└── 日志队列处理
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppMonitoringSystemIDisposable
{
/// <summary>
/// 工业设备基础类,实现IDisposable接口进行资源管理
/// </summary>
public class IndustrialDevice : IDisposable
{
private bool _disposed = false;
private CancellationTokenSource _cancellationTokenSource;
private Task _monitoringTask;
private readonly Random _random = new Random();
// 事件定义
public event EventHandler<DeviceDataEventArgs> DataReceived;
public event EventHandler<string> StatusChanged;
// 设备属性
public string DeviceId { get; private set; }
public string DeviceName { get; private set; }
public bool IsConnected { get; private set; }
public double Temperature { get; private set; }
public double Pressure { get; private set; }
public int Speed { get; private set; }
public IndustrialDevice(string deviceId, string deviceName)
{
DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId));
DeviceName = deviceName ?? throw new ArgumentNullException(nameof(deviceName));
_cancellationTokenSource = new CancellationTokenSource();
}
/// <summary>
/// 连接设备
/// </summary>
public async Task<bool> ConnectAsync()
{
if (_disposed) throw new ObjectDisposedException(nameof(IndustrialDevice));
try
{
OnStatusChanged("正在连接设备...");
await Task.Delay(2000); // 模拟连接时间
IsConnected = true;
OnStatusChanged($"设备 {DeviceName} 连接成功");
// 启动数据监控任务
_monitoringTask = Task.Run(MonitorDeviceData, _cancellationTokenSource.Token);
return true;
}
catch (Exception ex)
{
OnStatusChanged($"连接失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 断开设备连接
/// </summary>
public async Task DisconnectAsync()
{
if (!IsConnected) return;
try
{
OnStatusChanged("正在断开连接...");
// 取消监控任务
_cancellationTokenSource?.Cancel();
if (_monitoringTask != null)
{
await _monitoringTask;
}
IsConnected = false;
OnStatusChanged($"设备 {DeviceName} 已断开连接");
}
catch (Exception ex)
{
OnStatusChanged($"断开连接时发生错误: {ex.Message}");
}
}
/// <summary>
/// 监控设备数据的后台任务
/// </summary>
private async Task MonitorDeviceData()
{
try
{
while (!_cancellationTokenSource.Token.IsCancellationRequested && IsConnected)
{
// 模拟读取设备数据
Temperature = 20 + _random.NextDouble() * 60; // 20-80°C
Pressure = 1 + _random.NextDouble() * 9; // 1-10 Bar
Speed = 1000 + _random.Next(500); // 1000-1500 RPM
var data = new DeviceDataEventArgs
{
DeviceId = DeviceId,
Temperature = Temperature,
Pressure = Pressure,
Speed = Speed,
Timestamp = DateTime.Now
};
OnDataReceived(data);
await Task.Delay(1000, _cancellationTokenSource.Token);
}
}
catch (OperationCanceledException)
{
// 正常取消操作
}
catch (Exception ex)
{
OnStatusChanged($"数据监控错误: {ex.Message}");
}
}
protected virtual void OnDataReceived(DeviceDataEventArgs e)
{
DataReceived?.Invoke(this, e);
}
protected virtual void OnStatusChanged(string status)
{
StatusChanged?.Invoke(this, status);
}
#region IDisposable 实现
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 释放托管资源
try
{
DisconnectAsync().Wait(5000); // 最多等待5秒
}
catch
{
// 忽略断开连接时的异常
}
_cancellationTokenSource?.Dispose();
_monitoringTask?.Dispose();
}
// 释放非托管资源(如有)
_disposed = true;
}
}
~IndustrialDevice()
{
Dispose(false);
}
#endregion
}
/// <summary>
/// 设备数据事件参数
/// </summary>
public class DeviceDataEventArgs : EventArgs
{
public string DeviceId { get; set; }
public double Temperature { get; set; }
public double Pressure { get; set; }
public int Speed { get; set; }
public DateTime Timestamp { get; set; }
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppMonitoringSystemIDisposable
{
/// <summary>
/// 数据记录器,负责将设备数据写入文件
/// </summary>
public class DataLogger : IDisposable
{
private bool _disposed = false;
private StreamWriter _logWriter;
private readonly string _logFilePath;
private readonly Queue<string> _logQueue = new Queue<string>();
private readonly object _lockObject = new object();
public DataLogger(string logDirectory = "Logs")
{
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
_logFilePath = Path.Combine(logDirectory, $"DeviceLog_{DateTime.Now:yyyyMMdd_HHmmss}.csv");
InitializeLogFile();
}
private void InitializeLogFile()
{
try
{
_logWriter = new StreamWriter(_logFilePath, true);
_logWriter.WriteLine("Timestamp,DeviceId,Temperature,Pressure,Speed");
_logWriter.Flush();
}
catch (Exception ex)
{
throw new InvalidOperationException($"无法初始化日志文件: {ex.Message}", ex);
}
}
/// <summary>
/// 记录设备数据
/// </summary>
public async Task LogDataAsync(DeviceDataEventArgs data)
{
if (_disposed) throw new ObjectDisposedException(nameof(DataLogger));
try
{
var logEntry = $"{data.Timestamp:yyyy-MM-dd HH:mm:ss},{data.DeviceId}," +
$"{data.Temperature:F2},{data.Pressure:F2},{data.Speed}";
lock (_lockObject)
{
_logQueue.Enqueue(logEntry);
}
await FlushLogsAsync();
}
catch (Exception ex)
{
throw new InvalidOperationException($"记录数据时发生错误: {ex.Message}", ex);
}
}
/// <summary>
/// 刷新日志到文件
/// </summary>
private async Task FlushLogsAsync()
{
await Task.Run(() =>
{
lock (_lockObject)
{
while (_logQueue.Count > 0)
{
var logEntry = _logQueue.Dequeue();
_logWriter?.WriteLine(logEntry);
}
_logWriter?.Flush();
}
});
}
#region IDisposable 实现
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 刷新剩余的日志
try
{
FlushLogsAsync().Wait(3000);
}
catch
{
// 忽略刷新时的异常
}
// 释放托管资源
_logWriter?.Dispose();
}
_disposed = true;
}
}
#endregion
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppMonitoringSystemIDisposable
{
/// <summary>
/// 连接管理器,管理多个设备连接
/// </summary>
public class ConnectionManager : IDisposable
{
private bool _disposed = false;
private readonly Dictionary<string, IndustrialDevice> _devices;
private DataLogger _dataLogger;
public event EventHandler<DeviceDataEventArgs> DeviceDataReceived;
public event EventHandler<string> StatusChanged;
public ConnectionManager()
{
_devices = new Dictionary<string, IndustrialDevice>();
_dataLogger = new DataLogger();
}
/// <summary>
/// 添加设备
/// </summary>
public void AddDevice(string deviceId, string deviceName)
{
if (_disposed) throw new ObjectDisposedException(nameof(ConnectionManager));
if (_devices.ContainsKey(deviceId))
{
throw new ArgumentException($"设备ID {deviceId} 已存在");
}
var device = new IndustrialDevice(deviceId, deviceName);
device.DataReceived += OnDeviceDataReceived;
device.StatusChanged += OnDeviceStatusChanged;
_devices[deviceId] = device;
OnStatusChanged($"设备 {deviceName} (ID: {deviceId}) 已添加");
}
/// <summary>
/// 连接设备
/// </summary>
public async Task<bool> ConnectDeviceAsync(string deviceId)
{
if (_disposed) throw new ObjectDisposedException(nameof(ConnectionManager));
if (_devices.TryGetValue(deviceId, out var device))
{
return await device.ConnectAsync();
}
OnStatusChanged($"设备ID {deviceId} 不存在");
return false;
}
/// <summary>
/// 断开设备连接
/// </summary>
public async Task DisconnectDeviceAsync(string deviceId)
{
if (_disposed) throw new ObjectDisposedException(nameof(ConnectionManager));
if (_devices.TryGetValue(deviceId, out var device))
{
await device.DisconnectAsync();
}
}
/// <summary>
/// 断开所有设备连接
/// </summary>
public async Task DisconnectAllAsync()
{
var disconnectTasks = _devices.Values
.Where(d => d.IsConnected)
.Select(d => d.DisconnectAsync());
await Task.WhenAll(disconnectTasks);
}
/// <summary>
/// 获取设备列表
/// </summary>
public IEnumerable<IndustrialDevice> GetDevices()
{
return _devices.Values.ToList();
}
private async void OnDeviceDataReceived(object sender, DeviceDataEventArgs e)
{
try
{
// 记录数据到文件
await _dataLogger.LogDataAsync(e);
// 转发事件
DeviceDataReceived?.Invoke(this, e);
}
catch (Exception ex)
{
OnStatusChanged($"数据处理错误: {ex.Message}");
}
}
private void OnDeviceStatusChanged(object sender, string status)
{
StatusChanged?.Invoke(this, status);
}
protected virtual void OnStatusChanged(string status)
{
StatusChanged?.Invoke(this, status);
}
#region IDisposable 实现
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 断开所有设备连接
try
{
DisconnectAllAsync().Wait(10000);
}
catch
{
// 忽略断开连接时的异常
}
// 释放所有设备
foreach (var device in _devices.Values)
{
device?.Dispose();
}
_devices.Clear();
// 释放数据记录器
_dataLogger?.Dispose();
}
_disposed = true;
}
}
#endregion
}
}
C#namespace AppMonitoringSystemIDisposable
{
public partial class Form1 : Form
{
private ConnectionManager _connectionManager;
private bool _formClosing = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeSystem();
}
/// <summary>
/// 初始化系统
/// </summary>
private void InitializeSystem()
{
try
{
_connectionManager = new ConnectionManager();
_connectionManager.DeviceDataReceived += OnDeviceDataReceived;
_connectionManager.StatusChanged += OnStatusChanged;
LogStatus("✅ 工业设备监控系统初始化完成");
LogStatus("📋 请添加设备开始监控...");
toolStripStatusLabel.Text = "系统就绪 - 等待设备连接";
}
catch (Exception ex)
{
LogStatus($"❌ 系统初始化失败: {ex.Message}");
MessageBox.Show($"系统初始化失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 添加设备
/// </summary>
private void buttonAddDevice_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxDeviceId.Text) ||
string.IsNullOrWhiteSpace(textBoxDeviceName.Text))
{
MessageBox.Show("请输入设备编号和设备名称!", "输入错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
_connectionManager.AddDevice(textBoxDeviceId.Text.Trim(),
textBoxDeviceName.Text.Trim());
RefreshDeviceList();
// 清空输入框
textBoxDeviceId.Clear();
textBoxDeviceName.Clear();
}
catch (Exception ex)
{
MessageBox.Show($"添加设备失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// 连接设备
/// </summary>
private async void buttonConnect_Click(object sender, EventArgs e)
{
if (listViewDevices.SelectedItems.Count == 0)
{
MessageBox.Show("请先选择一个设备!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var selectedDeviceId = listViewDevices.SelectedItems[0].SubItems[0].Text;
try
{
toolStripProgressBar.Visible = true;
toolStripProgressBar.Style = ProgressBarStyle.Marquee;
toolStripStatusLabel.Text = "正在连接设备...";
var success = await _connectionManager.ConnectDeviceAsync(selectedDeviceId);
if (success)
{
RefreshDeviceList();
toolStripStatusLabel.Text = "设备连接成功";
}
else
{
toolStripStatusLabel.Text = "设备连接失败";
}
}
catch (Exception ex)
{
LogStatus($"❌ 连接设备时发生错误: {ex.Message}");
toolStripStatusLabel.Text = "连接设备失败";
}
finally
{
toolStripProgressBar.Visible = false;
}
}
/// <summary>
/// 断开设备连接
/// </summary>
private async void buttonDisconnect_Click(object sender, EventArgs e)
{
if (listViewDevices.SelectedItems.Count == 0)
{
MessageBox.Show("请先选择一个设备!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var selectedDeviceId = listViewDevices.SelectedItems[0].SubItems[0].Text;
try
{
toolStripProgressBar.Visible = true;
toolStripProgressBar.Style = ProgressBarStyle.Marquee;
toolStripStatusLabel.Text = "正在断开设备连接...";
await _connectionManager.DisconnectDeviceAsync(selectedDeviceId);
RefreshDeviceList();
toolStripStatusLabel.Text = "设备已断开连接";
}
catch (Exception ex)
{
LogStatus($"❌ 断开设备时发生错误: {ex.Message}");
toolStripStatusLabel.Text = "断开设备失败";
}
finally
{
toolStripProgressBar.Visible = false;
}
}
/// <summary>
/// 断开所有设备连接
/// </summary>
private async void buttonDisconnectAll_Click(object sender, EventArgs e)
{
var result = MessageBox.Show("确定要断开所有设备连接吗?", "确认操作",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
try
{
toolStripProgressBar.Visible = true;
toolStripProgressBar.Style = ProgressBarStyle.Marquee;
toolStripStatusLabel.Text = "正在断开所有设备连接...";
await _connectionManager.DisconnectAllAsync();
RefreshDeviceList();
toolStripStatusLabel.Text = "所有设备已断开连接";
}
catch (Exception ex)
{
LogStatus($"❌ 断开所有设备时发生错误: {ex.Message}");
toolStripStatusLabel.Text = "断开设备失败";
}
finally
{
toolStripProgressBar.Visible = false;
}
}
}
/// <summary>
/// 设备选择改变事件
/// </summary>
private void listViewDevices_SelectedIndexChanged(object sender, EventArgs e)
{
if (listViewDevices.SelectedItems.Count > 0)
{
var selectedItem = listViewDevices.SelectedItems[0];
var deviceId = selectedItem.SubItems[0].Text;
var deviceName = selectedItem.SubItems[1].Text;
labelSelectedDevice.Text = $"📟 {deviceName} ({deviceId})";
// 更新实时数据显示
UpdateRealTimeData(selectedItem);
}
else
{
labelSelectedDevice.Text = "请选择一个设备...";
ClearRealTimeData();
}
}
/// <summary>
/// 更新实时数据显示
/// </summary>
private void UpdateRealTimeData(ListViewItem item)
{
if (item.SubItems.Count >= 6)
{
labelTemperatureValue.Text = item.SubItems[3].Text;
labelPressureValue.Text = item.SubItems[4].Text;
labelSpeedValue.Text = item.SubItems[5].Text;
}
}
/// <summary>
/// 清空实时数据显示
/// </summary>
private void ClearRealTimeData()
{
labelTemperatureValue.Text = "0.0°C";
labelPressureValue.Text = "0.0 Bar";
labelSpeedValue.Text = "0 RPM";
}
/// <summary>
/// 定时器更新事件
/// </summary>
private void timerUpdate_Tick(object sender, EventArgs e)
{
if (!_formClosing)
{
RefreshDeviceList();
}
}
/// <summary>
/// 刷新设备列表
/// </summary>
private void RefreshDeviceList()
{
try
{
var selectedDeviceId = listViewDevices.SelectedItems.Count > 0 ?
listViewDevices.SelectedItems[0].SubItems[0].Text : null;
listViewDevices.Items.Clear();
foreach (var device in _connectionManager.GetDevices())
{
var item = new ListViewItem(device.DeviceId);
item.SubItems.Add(device.DeviceName);
item.SubItems.Add(device.IsConnected ? "🟢 已连接" : "🔴 未连接");
item.SubItems.Add(device.IsConnected ? $"{device.Temperature:F1}°C" : "N/A");
item.SubItems.Add(device.IsConnected ? $"{device.Pressure:F1} Bar" : "N/A");
item.SubItems.Add(device.IsConnected ? $"{device.Speed} RPM" : "N/A");
// 设置行颜色
if (device.IsConnected)
{
item.BackColor = Color.LightGreen;
}
else
{
item.BackColor = Color.LightGray;
}
listViewDevices.Items.Add(item);
// 恢复选择状态
if (device.DeviceId == selectedDeviceId)
{
item.Selected = true;
UpdateRealTimeData(item);
}
}
// 更新连接统计
var connectedCount = _connectionManager.GetDevices().Count(d => d.IsConnected);
var totalCount = _connectionManager.GetDevices().Count();
toolStripStatusLabel.Text = $"设备状态: {connectedCount}/{totalCount} 已连接";
}
catch (Exception ex)
{
LogStatus($"❌ 刷新设备列表时发生错误: {ex.Message}");
}
}
/// <summary>
/// 设备数据接收事件处理
/// </summary>
private void OnDeviceDataReceived(object sender, DeviceDataEventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<object, DeviceDataEventArgs>(OnDeviceDataReceived), sender, e);
return;
}
// 在这里可以处理接收到的设备数据
// 例如更新图表、检查报警条件等
// 检查温度报警
if (e.Temperature > 70)
{
LogStatus($"⚠️ 警告: 设备 {e.DeviceId} 温度过高 ({e.Temperature:F1}°C)");
}
// 检查压力报警
if (e.Pressure > 8)
{
LogStatus($"⚠️ 警告: 设备 {e.DeviceId} 压力过高 ({e.Pressure:F1} Bar)");
}
}
/// <summary>
/// 状态变更事件处理
/// </summary>
private void OnStatusChanged(object sender, string status)
{
if (InvokeRequired)
{
Invoke(new Action<object, string>(OnStatusChanged), sender, status);
return;
}
LogStatus(status);
}
/// <summary>
/// 记录状态日志
/// </summary>
private void LogStatus(string message)
{
if (_formClosing || IsDisposed || textBoxStatus.IsDisposed)
return;
try
{
if (InvokeRequired)
{
// 使用BeginInvoke避免阻塞,并且更安全
BeginInvoke(new Action<string>(LogStatus), message);
return;
}
if (textBoxStatus.IsDisposed)
return;
var timestamp = DateTime.Now.ToString("HH:mm:ss");
var logEntry = $"[{timestamp}] {message}";
textBoxStatus.AppendText(logEntry + Environment.NewLine);
textBoxStatus.SelectionStart = textBoxStatus.Text.Length;
textBoxStatus.ScrollToCaret();
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debug.WriteLine($"[{DateTime.Now:HH:mm:ss}] {message}");
}
catch (InvalidOperationException)
{
System.Diagnostics.Debug.WriteLine($"[{DateTime.Now:HH:mm:ss}] {message}");
}
}
/// <summary>
/// 菜单 - 退出
/// </summary>
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
/// <summary>
/// 菜单 - 关于
/// </summary>
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show(
"🏭 工业设备监控系统\n\n" +
"这是一个演示 IDisposable 接口应用的完整示例程序。\n\n" +
"主要功能:\n" +
"• 设备连接管理\n" +
"• 实时数据采集\n" +
"• 数据记录和日志\n" +
"• 资源自动释放\n\n" +
"技术特点:\n" +
"• 完整的 IDisposable 实现\n" +
"• 异步编程模式\n" +
"• 事件驱动架构\n" +
"• 线程安全设计\n\n"
);
}
/// <summary>
/// 窗体关闭事件
/// </summary>
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_formClosing = true;
if (_connectionManager != null)
{
try
{
LogStatus("🔄 正在关闭系统...");
// 显示关闭进度
toolStripProgressBar.Visible = true;
toolStripProgressBar.Style = ProgressBarStyle.Marquee;
toolStripStatusLabel.Text = "正在安全关闭系统...";
// 等待系统安全关闭
await Task.Run(() =>
{
_connectionManager.Dispose();
});
LogStatus("✅ 系统已安全关闭");
}
catch (Exception ex)
{
LogStatus($"❌ 关闭系统时发生错误: {ex.Message}");
}
}
}
}
}
C#// ✅ 推荐:使用using语句自动管理资源
public async Task ProcessDataAsync()
{
using var manager = new ConnectionManager();
manager.AddDevice("PLC001", "主控制器");
await manager.ConnectDeviceAsync("PLC001");
// 方法结束时自动调用Dispose()
}
// C# 8.0+ 更简洁的写法
using var connection = new SqlConnection(connectionString);
connection.Open();
// 作用域结束时自动释放
C#public class AsyncResourceManager : IAsyncDisposable, IDisposable
{
public async ValueTask DisposeAsync()
{
await DisposeAsyncCore();
Dispose(false);
GC.SuppressFinalize(this);
}
protected virtual async ValueTask DisposeAsyncCore()
{
// 异步释放资源
if (_httpClient != null)
{
await _httpClient.GetAsync("/api/disconnect");
_httpClient.Dispose();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
陷阱1:在Dispose中抛出异常
C#// ❌ 错误:可能导致程序崩溃
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_fileStream.Close(); // 可能抛出异常
}
}
// ✅ 正确:捕获异常
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
try
{
_fileStream?.Close();
}
catch (Exception ex)
{
// 记录日志但不抛出异常
Debug.WriteLine($"Dispose error: {ex.Message}");
}
}
}
陷阱2:忘记检查disposed状态
C#public void DoSomething()
{
if (_disposed) throw new ObjectDisposedException(nameof(MyClass));
// 业务逻辑
}
在实际的Windows应用程序中,正确的资源管理同样重要:
C#public partial class Form1 : Form
{
private ConnectionManager _connectionManager;
private bool _formClosing = false;
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_formClosing = true;
if (_connectionManager != null)
{
try
{
// 🎯 关键:在窗体关闭前安全释放资源
await Task.Run(() => _connectionManager.Dispose());
}
catch (Exception ex)
{
Debug.WriteLine($"关闭时发生错误: {ex.Message}");
}
}
}
// 线程安全的日志记录
private void LogStatus(string message)
{
if (_formClosing || IsDisposed)
return;
try
{
if (InvokeRequired)
{
BeginInvoke(new Action<string>(LogStatus), message);
return;
}
textBoxStatus.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\n");
}
catch (ObjectDisposedException)
{
// UI已释放,写入调试输出
Debug.WriteLine(message);
}
}
}
C#public class OptimizedDisposable : IDisposable
{
private int _disposed = 0; // 使用int代替bool,支持原子操作
public void Dispose()
{
// 原子性检查和设置,避免重复释放
if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0)
{
DisposeCore();
GC.SuppressFinalize(this);
}
}
private void DisposeCore()
{
// 实际释放逻辑
}
}
C#// 对于集合类型的资源,使用Parallel.ForEach提高性能
protected override void Dispose(bool disposing)
{
if (disposing)
{
Parallel.ForEach(_devices.Values, device => device?.Dispose());
}
}
通过这个完整的工业监控系统案例,我们深入掌握了IDisposable接口的核心要点:
🔥 三个关键原则:
这套资源管理模式不仅适用于文件和网络操作,更是构建高质量C#应用程序的基石。掌握了这些技巧,你的程序将更加稳定、高效,再也不用担心资源泄露问题!
💭 互动问题:
🚀 如果这篇文章对你有帮助,请转发给更多的C#开发同行,让我们一起写出更优雅的代码!
关注公众号,获取更多C#实战干货和最新技术动态!
相关信息
通过网盘分享的文件:AppMonitoringSystemIDisposable.zip 链接: https://pan.baidu.com/s/1d5_fLHfHsmJnPYx_H4uydQ?pwd=ezcu 提取码: ezcu --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!