使用串口时出现“尝试读写受保护内存”错误的排查求助
Hey, that "Attempted to read or write protected memory" error and accelerating crashes are classic signs of unmanaged resources not being cleaned up properly, plus event handler leaks. Let’s break down the issues in your code and fix them step by step:
1. Timer Event Handlers Are Piling Up (Big Memory Leak)
Every time you click button1, you’re adding a new Tick handler to preparation_delay—but you only remove it once in the start method. If the user clicks the button multiple times, you end up with duplicate event bindings. Worse, fire_time and measurement_time never have their handlers removed at all!
Timers hold strong references to their event targets (your Form), so those references stick around even if you stop the timer. Over time, this creates a memory leak that gets worse with each run.
Fix It:
- Always remove old handlers before adding new ones to avoid duplicates
- Dispose all timers when the form closes, after removing their handlers:
private void button1_Click(object sender, EventArgs e) { // Clean up old bindings first to prevent duplicates preparation_delay.Tick -= start; preparation_delay.Interval = 1000; preparation_delay.Tick += start; preparation_delay.Start(); // Do the same for your other timers measurement_time.Tick -= stop; measurement_time.Interval = 60000; measurement_time.Tick += stop; fire_time.Tick -= FIRE; fire_time.Interval = Convert.ToInt32(textBox6.Text) * 1000; fire_time.Tick += FIRE; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // Stop and clean up all timers preparation_delay.Stop(); preparation_delay.Tick -= start; preparation_delay.Dispose(); measurement_time.Stop(); measurement_time.Tick -= stop; measurement_time.Dispose(); fire_time.Stop(); fire_time.Tick -= FIRE; fire_time.Dispose(); // ... rest of your cleanup code ... }
2. Resource Release Order Is Wrong & Redundant
In your Write_to_Text catch block, you’re calling this.Dispose() before this.Close()—that’s backwards! You should always close the form first to release UI resources, then dispose of any remaining objects. Also, manually calling this.Dispose() in Form1_FormClosing is redundant: WinForms handles form disposal automatically when it closes. You only need to clean up the resources you created (serial ports, GPIB, timers).
Fix the Catch Block:
catch (Exception ex) { // Stop all timers first fire_time.Stop(); measurement_time.Stop(); preparation_delay.Stop(); // Clean up serial ports safely if (serialPort1.IsOpen) serialPort1.Close(); if (Arduino != null && Arduino.IsOpen) Arduino.Close(); // Dispose GPIB GPIB?.Dispose(); // Just close the form—no need to call Dispose manually this.Close(); }
3. Your Device Objects Might Be Holding Resources
Your DMM1, DMM2, DMM3 instances are class-level fields, but I don’t see you disposing them anywhere. If these Device objects wrap GPIB connections or other unmanaged resources, they’ll leak memory until you dispose them.
Add This to FormClosing:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { // ... existing cleanup code ... // Dispose your device objects if they implement IDisposable DMM1?.Dispose(); DMM2?.Dispose(); DMM3?.Dispose(); }
4. Serial Port Initialization Checks
Make sure in InitializePorts you’re not creating new SerialPort instances without disposing old ones. For example, if Arduino is already initialized, don’t create a new one—this would leave the old instance hanging in memory. Also, always check if a port is open before closing it to avoid exceptions.
Bonus: Use using for Short-Lived Resources
While File.AppendAllText works, using a StreamWriter with using ensures the file handle is released immediately, even if an error occurs. It’s a safer pattern for file operations:
private void Write_to_Text(string time_date, string PRC_Reading, string[] DMM_Reading) { string string_to_save = "..."; try { using (var writer = new StreamWriter(filename, true)) { writer.WriteLine(string_to_save); } } catch (Exception ex) { // Your error handling here } }
These changes should eliminate the memory buildup and protected memory errors by ensuring all unmanaged resources are cleaned up, event references are removed, and you’re not creating redundant object instances that can’t be garbage collected.
内容的提问来源于stack exchange,提问作者Amin

