ObjectDisposedException, когда .Show () использует форму, которая не должна быть удалена - PullRequest
3 голосов
/ 20 апреля 2010

Я проверил некоторые другие вопросы, и, очевидно, лучшее решение - это в первую очередь предотвратить поведение, вызывающее эту проблему, но проблема очень прерывистая и очень невоспроизводимая.

У меня, в основном, есть основная форма с вложенными формами. Подформы отображаются из меню и / или кнопок основной формы следующим образом:


private void myToolStripMenuItem_Click(object sender, EventArgs e)
{
    try
    {
        xDataForm.Show();
        xDataForm.Activate();
    }
    catch (ObjectDisposedException)
    {
        MessageBox.Show("ERROR 10103");
        ErrorLogging newLogger = new ErrorLogging("10103");
        Thread errorThread = new Thread(ErrorLogging.writeErrorToLog);
        errorThread.Start();
    }
}

и субформы на самом деле находятся в основной форме (к лучшему или к худшему. Я бы на самом деле хотел это изменить, но у меня было бы достаточно времени):


public partial class FormMainScreen : Form
{
    Form xDataForm = new xData();
    ...(lots more here)

    public FormMainScreen(int pCount, string pName)
 {
        InitializeComponent();
        ...
 }
    ...
}

Функция Dispose для подформы изменена таким образом, что кнопки «закрыть» и «X» фактически скрывают форму, поэтому нам не нужно каждый раз заново ее создавать. Когда главный экран закрывается, он устанавливает «флаг» в 2, так что другие формы знают, что на самом деле можно закрыть;


protected override void Dispose(bool disposing)
{
    if (FormMainScreen.isExiting == 2) 
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    else
    {
        if (xData.ActiveForm != null)
        {
            xData.ActiveForm.Hide();
        }
    }
}

Итак, вопрос в том, почему эта работа снова и снова и снова безупречна, но, буквально, примерно в каждой 1/1000 времени, вызывает исключение, или, скорее, почему моя форма утилизируется?

У меня было подозрение, что сборщик мусора запутался, потому что он происходит немного чаще после того, как он работал в течение многих часов.

Ответы [ 2 ]

3 голосов
/ 20 апреля 2010

Без обид, но это, кажется, очень запутанное решение проблемы, которая была решена очень давно.

Вы не должны делать ничего в методе Dispose (), кроме утилизации других одноразовых (и даже тогда, только если флаг утилизации имеет значение true). Поэтому я бы не стал изменять метод, сгенерированный для вас дизайнером. *

Таким образом, немедленный ответ на ваш вопрос о том, почему это происходит, почти наверняка связан с синхронизацией сборщика мусора, вызывающего ваш метод Dispose.

Вместо этого вам, вероятно, следует рассмотреть возможность использования родительской формы MDI ( интерфейс с несколькими документами ), а ваши «подформы» называются дочерними MDI. Затем вы можете обработать событие FormClosing у детей следующим образом.

(Обратите внимание, что если вы против MDI, вы можете сделать в основном то же самое, используя форму Владельцы .)

// MDI child
private void Form_FormClosing(object sender, FormClosingEventArgs e) {
    if (e.CloseReason == CloseReason.UserClosing) {
        e.Cancel = true;
        Hide();
    }
}

Когда форма закрывается по различным причинам, таким как закрытие в коде, родительская форма закрывается, Windows закрывается и т. Д., Тогда закрытие не будет отменено. Только когда окно закрывается, потому что пользователь закрыл дочернюю форму напрямую, вы можете ее скрыть.

Чтобы показать дочернего элемента MDI внутри родительского MDI, вы можете сделать следующее:

MyParentForm parentForm = new MyParentForm();
parentForm.IsMdiContainer = true;
parentForm.Show();

MyChildForm childForm = new MyChildForm();
childForm.MdiParent = parentForm;
childForm.Show();
2 голосов
/ 20 апреля 2010
try 
{
    // Validate form not disposed before using. Initialize as needed. 
    if  (xDataForm == null || xDataForm.IsDisposed)
    {
        xDataForm = new MyDataFormName();
    }
    xDataForm.Show(); 
    xDataForm.Activate(); 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...