使用串行端口时,出现错误:尝试读取或写入受保护的内存 [英] Using serial ports, I get an error: Attempted to read or write protected memory

查看:93
本文介绍了使用串行端口时,出现错误:尝试读取或写入受保护的内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道以前有人问过这个问题,但现有的答案都没有解决我的问题.我有一个 WinForms 应用程序,它与许多设备通信,获取数据并将它们写入文件.

I know this question has been asked before but none of the existing answers solved my problem. I have a WinForms Application which communicates with a number of devices, takes data and writes them to a file.

它打开 GPIB 和串行端口通信,最后关闭所有这些.我使用 this.Dispose()this.Close() 来确保内存被释放(至少我认为内存被释放).但是,下次我运行它时,几个小时后我收到错误:

It opens GPIB and Serial port communications and at the end closes all of them. I use this.Dispose() and this.Close() to make sure that memory is released (at least I think the memory is released). However, next time I run it, after several hours I get the error:

试图读取或写入受保护的内存.这通常是一个指示其他内存已损坏.

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

如果我再次运行它,崩溃时间会变得越来越短,就像内存中积累了一些东西.我复制了似乎与此问题相关的部分代码.我在内存消耗方面犯了什么错误吗?

If I run it again the crash time becomes shorter and shorter as if something is accumulating in memory. I copy parts of my code that seem to be related to this issue. Am I making any mistake in memory consumption?

我的尝试:

添加了 this.Dispose()Close() 函数来关闭端口(最初我忘记添加它们).但仍然没有帮助.我还尝试在每次运行前重新启动计算机,但也无济于事.

Added this.Dispose() and the Close() functions to close the ports (initially I forgot to add them). But still did not help. I also tried to restart my computer before each run, yet it did not help either.

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();
    }
}

推荐答案

每当你发现自己手动调用了 Dispose() 函数时,这有点代码味道......不对.

Whenever you find yourself manually calling the Dispose() function, that's a bit of a code smell... an indication something is not right.

相反,学习使用 using 关键字来创建包装一次性对象的块.这将帮助您为这些对象创建有意义的范围边界.它还有助于避免错误,其中 Close()Dispose() 调用没有用 finally 块正确包装.

Instead, learn to use the using keyword to create blocks that wrap disposable objects. This will help you create meaningful scope boundaries for the those objects. It also helps avoid mistakes, where Close() and Dispose() calls were not properly wrapped with a finally block.

在这种情况下,问题可能涉及以下代码片段:

In this case, the problem likely involves these code snippets:

this.Dispose();
this.Close();

永远不要从要处理的对象本身内部调用 Dispose()(除非作为实现核心 IDisposable 模式的一部分).相反,由外部代码告诉您的对象何时完成.在这里,您尝试Dispose()一个表单之前Form_Closing 方法被引发(参见Write_To_Text()),这意味着当 Form_Closing() 本身尝试执行时表单无效.

Never call Dispose() from inside the object itself you want to dispose (except as part of implementing the core IDisposable pattern). Instead, it's up to the outside code to tell your object when it's finished. Here, you attempt to Dispose() a form before the Form_Closing method is raised (see Write_To_Text()), meaning the form is invalid when Form_Closing() itself tries to execute.

这篇关于使用串行端口时,出现错误:尝试读取或写入受保护的内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆