Используя последовательные порты, я получаю сообщение об ошибке: Попытка чтения или записи в защищенную память - PullRequest
0 голосов
/ 09 мая 2018

Я знаю, что этот вопрос задавался ранее, но ни один из существующих ответов не решил мою проблему. У меня есть приложение 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();
    }
}

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Всякий раз, когда вы обнаруживаете, что вызываете функцию Dispose() вручную, это немного пахнет кодом ... признак того, что что-то не так.

Вместо этого научитесь использовать ключевое слово using для создания блоков, которые обертывают одноразовые объекты. Это поможет вам создать значимые границы области действия для этих объектов. Это также помогает избежать ошибок, когда вызовы Close() и Dispose() не были должным образом упакованы в блок finally.

В этом случае проблема, вероятно, связана со следующими фрагментами кода:

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

Никогда не вызывайте Dispose() изнутри самого объекта, который вы хотите удалить (кроме как в рамках реализации базового шаблона IDisposable). Вместо этого, внешний код должен сообщить вашему объекту, когда он закончится. Здесь вы пытаетесь Dispose() создать форму до того, как будет вызван метод Form_Closing (см. Write_To_Text()), что означает, что форма недопустима, когда сама Form_Closing () пытается выполнить.

0 голосов
/ 30 мая 2018

В принципе, для нативных объектов NET вам не нужно явно вызывать Dispose (это сделает финализатор), но если у вас есть какие-то внешние объекты, обращающиеся к внешним ресурсам (GPIB?), Вы должны быть осторожны.Я вижу, что если в Write_To_Text есть исключение, вы вызовете GPIB.Dispose дважды, а также то, что оно может быть вызвано до того, как таймеры будут эффективно остановлены.Убедитесь, что после того, как вы утилизируете ее, не будет никакого вызова какой-либо функции Gpib (например, установите флаг, который будет проверяться перед вызовом функций Gpib).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...