使用串行端口,我收到一个错误:尝试读取或写入受保护的内存
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用串行端口,我收到一个错误:尝试读取或写入受保护的内存相关的知识,希望对你有一定的参考价值。
我知道之前已经问过这个问题,但现有的答案都没有解决我的问题。我有一个WinForms应用程序,它与许多设备通信,获取数据并将它们写入文件。
它打开GPIB和串口通信,最后关闭所有这些通信。我使用this.Dispose()
和this.Close()
来确保释放内存(至少我认为内存已被释放)。但是,下次我运行它,几个小时后我收到错误:
尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
如果我再次运行它,崩溃时间会越来越短,就像内存中积累的东西一样。我复制了与此问题相关的部分代码。我在内存消耗方面有任何错误吗?
我尝试了什么:
添加了this.Dispose()
和Close()
函数来关闭端口(最初我忘了添加它们)。但仍然没有帮助。我还尝试在每次运行之前重新启动计算机,但它也没有帮助。
public partial class Form1 : Form
{
//GPIB and serial ports
SerialPort Arduino;
SerialPort serialPort1 = new SerialPort();
private Device DMM1, DMM2, DMM3;
private Address DMM1_Address, DMM2_Address, DMM3_Address;
private Address[] Address_List = new Address[3];
private AddressCollection GPIB_Adds;
Board GPIB = new Board(0);
//Timers
System.Windows.Forms.Timer fire_time = new System.Windows.Forms.Timer();
System.Windows.Forms.Timer measurement_time = new System.Windows.Forms.Timer();
System.Windows.Forms.Timer preparation_delay = new System.Windows.Forms.Timer();
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
public Form1()
{
// ...some code
}
private void InitializePorts()
{
// ...ports are initialized here
}
private void button1_Click(object sender, EventArgs e)
{
preparation_delay.Interval = 1000;
preparation_delay.Tick += new EventHandler(start);
preparation_delay.Start();
measurement_time.Interval = 60000;
measurement_time.Tick += new EventHandler(stop);
fire_time.Interval = Convert.ToInt32(textBox6.Text) * 1000;
fire_time.Tick += new EventHandler(FIRE);
}
}
private void start(object obj, EventArgs e)
{
stopwatch.Start();
measurement_time.Start();
fire_time.Start();
preparation_delay.Stop();
preparation_delay.Tick -= new EventHandler(start);
//Here I try to annihilate the event handler in fear of staying in memory
}
private void FIRE(object obj, EventArgs e)
{
string p = //Reads data from device
string[] k = //Reads data from device
string t = //Reads data from device
Write_to_Text(t, p, k);
}
private void stop(object obj, EventArgs e)
{
fire_time.Stop();
measurement_time.Stop();
progress.Stop();
}
private void Write_to_Text(string time_date, string PRC_Reading, string[] DMM_Reading)
{
string string_to_save = ...some string
try
{
System.IO.File.AppendAllText(@filename, string_to_save);
}
catch (Exception ex)
{
serialPort1.Close();
Arduino.Close();
GPIB.Dispose();
measurement_time.Stop();
fire_time.Stop();
this.Dispose();
this.Close();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
serialPort1.Close();
Arduino.Close();
GPIB.Dispose();
this.Dispose();
this.Close();
}
}
原则上,对于本机NET对象,您不需要显式调用Dispose(终结器将执行此操作),但如果您有一些外部对象访问外部资源(GPIB?),则必须小心。我看到的是,如果Write_To_Text中存在异常,您将调用GPIB.Dispose两次,并且还可以在定时器有效停止之前调用它。确保在处理之后不会调用任何Gpib函数(例如,设置一个在调用Gpib函数之前将检查的标志)。
每当你发现自己手动调用Dispose()
函数时,这有点代码味道......这表明某些事情是不对的。
相反,学习使用using
关键字来创建包装一次性对象的块。这将帮助您为这些对象创建有意义的范围边界。它还有助于避免错误,其中Close()
和Dispose()
调用没有用finally
块正确包裹。
在这种情况下,问题可能涉及以下代码段:
this.Dispose();
this.Close();
永远不要从你想要处理的对象内部调用Dispose()
(除了作为实现核心IDisposable
模式的一部分)。相反,它取决于外部代码,告诉您的对象何时完成。在这里,你尝试在引发Dispose()
方法之前Form_Closing
表格(参见Write_To_Text()
),这意味着当Form_Closing()本身试图执行时表单无效。
以上是关于使用串行端口,我收到一个错误:尝试读取或写入受保护的内存的主要内容,如果未能解决你的问题,请参考以下文章
试图读取或写入受保护的内存-Sql Compact 和 .NEt