簡體   English   中英

無法訪問已處置的對象錯誤

[英]Cannot access a disposed object error

我收到錯誤消息無法訪問已處置的對象。 對象名稱:'ApplicationProperties'。 當我在關閉它之后嘗試重新打開表單時。 我注意到這是從退出表單,並退出是“處置”它們,所以我已將以下代碼放在我的所有接受按鈕,並取消按鈕(任何關閉表單的按鈕)。

 this.Hide(); 
 this.Parent = null;

這段代碼只是隱藏了表單。 沒有關閉表格。

所以我的問題是,當我單擊表單上的“x”按鈕,然后嘗試重新打開表單時仍然會收到錯誤消息。 我嘗試了幾種不同的方法來修改表單的現有功能,例如:

    private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

但這讓我沒有運氣。 我想知道是否有人知道如何解決這個問題。 這是在我的取消和接受按鈕內為我工作的代碼。 關閉表單的所有按鈕都是一樣的。

    private void OptionsCancelbtn_Click(object sender, EventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

我已經在form1的類頂部聲明了實例,並在form1中有一個打開form2的按鈕。

public partial class MainBox : Form
{
    //Making a name for the ApplicationProperties form. It can be opened when called.
    ApplicationProperties ApplicationPropertiesWindow = new ApplicationProperties();
    private void ApplicationPropertiesbtn_Click(object sender, EventArgs e)
    {
        //Show the properties window.
        ApplicationPropertiesWindow.Show();
    }//End ApplicationProperties button.
 }

在我使用第二個表單上的“x”按鈕關閉程序后,由於在ApplicationPropertiesWindow.Show();觸發了錯誤消息,因此無法再次訪問form2 ApplicationPropertiesWindow.Show();

在form2中我有以下代碼:

public partial class ApplicationProperties : Form
{
    //Creates and sets the instance MainBoxWindow.
    public MainBox MainBoxWindow { get; set; }

FormClosing事件中嘗試此FormClosing

  private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
  {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
        e.Cancel = true; //hides the form, cancels closing event
   }

因為現在它仍在關閉表格,因此仍然導致錯誤。

在我使用第二個表單上的“x”按鈕關閉程序后,由於在ApplicationPropertiesWindow.Show();觸發了錯誤消息,因此無法再次訪問form2 ApplicationPropertiesWindow.Show();

當窗體關閉( Form.Close )時,表單本身及其所有相關資源都將被釋放。 如文檔中所述,此自動處理只有兩個例外:

  1. 該表單是MDI應用程序的一部分, 可見。
  2. 使用ShowDialog (而不是Show )將表單顯示為模式對話框。 它以這種方式設計,以便您可以在用戶關閉對話框后訪問對話框的屬性(例如,檢索用戶輸入)。

在這兩種特殊情況下,您都負責手動調用表單的Dispose方法。 第二種情況是迄今為止最常見的(沒有人真正使用MDI范例),並且using語句可以輕松處理:

using (MyDialogBox dlg = new MyDialogBox())
{
    DialogResult result = dlg.ShowModal(this);
    if (result == DialogResult.Yes)
    {
        // access members of "dlg", and
        // do whatever the user asked
    }
}  // the Dispose method is automatically called here

在您的情況下,通常情況下,對Close方法的調用正在關閉並銷毀表單。 您已經知道您無法訪問已處置的對象(因為它不再存在!),因此當您嘗試顯示它時,這就是您獲得異常的原因。 為了在關閉后再次顯示表單,您需要創建表單類的新實例:

MyForm frm = new MyForm();
frm.Show();
// ...
frm.Close();

這確實是最好的方法。 表單的新實例將與您關閉的實例相同,因為它是從同一個類創建的。 您最好開始考慮面向對象的術語,盡可能避免使用基於單件的設計。 屏幕上顯示的每個表單都是一個新的獨立對象 一旦該對象被關閉並銷毀,您就不能再使用它了。 如果要再次使用它,則需要創建一個新對象並顯示它。

Hide方法更像是一個hack,只有當你想要暫時隱藏表單的當前實例同時仍保留其狀態(例如,其成員屬性的值,其控制狀態等)時才有用。 這僅適用於永遠不會被銷毀的單件對象,必須仔細設計和維護。 這也意味着這個表單對象一直消耗資源,無論是否正在使用,這都是浪費。

如果必須這樣做,則需要跟蹤導致表單實例處理的原因。 在沒有看到所有代碼的情況下,我很難做任何事情,但要猜測問題可能在哪里。 它可能與您使用AcceptButton和/或CancelButton屬性有關。 無論哪種方式,最好和最干凈的解決方案是覆蓋OnFormClosing方法並防止您的表單被關閉。 你會隱藏它:

public class MyForm : Form
{
    protected virtual void OnFormClosing(FormClosingEventArgs e)
    {
        // Prevent the form from closing.
        e.Cancel = true;

        // Hide it instead.
        this.Hide();
    }

    // ...other code in your form class
}    

這樣做的好處是,您只需將代碼放在一個位置,在負責類的本地,而不是暴露給外部代碼並分散在整個應用程序中。 當然,它還可以防止表單被控制之外的框架代碼關閉。

我不知道你為什么要將Parent屬性設置為null 頂級窗口(所有表單都是這樣)可以永遠不會有父級。 只有子窗口(例如控件)才有父母。 可以有一個所有者,但不一定。 這取決於在調用Show方法時是否將所有者窗口作為參數傳遞。

首先刪除this.Parent = null bcose隱藏表單時不需要這樣做

現在,當您隱藏表單時,如果您仍想在靜態var中訪問此表單存儲表單。 當對象不再使用時,Bcous垃圾收集器處理它並且它將不再可用。

問題,至少可能是其中的一部分,看起來像是階級相互依賴。

初始化ApplicationProperties實例時,您正在創建對MainBox對象的引用,但是在MainBox類的定義中,您正在創建一個引用MainBox的新ApplicationsProperties對象....我甚至讓自己感到困惑。 MainBox是您的父表單,即啟動應用程序時加載的表單嗎?

如果在ApplicationProperites類中設置對它的引用,那么當MainBox某些東西被無意中破壞時,我會不會感到驚訝...當你點擊“X”時它會被處置MainBox 再次,這是一個有根據的猜測; 我不確定這是不是原因,但即使代碼本身沒有 ,它對我來說也很古怪。

如果您希望ApplicationProperties窗口永遠持續並簡化操作,只需在應用程序持續時間的任何形式的開頭初始化它的靜態實例,並顯示/隱藏它類似於您最初嘗試的內容。 如果你想要高效和基礎,只要你需要讓用戶修改它就構造和處理ApplicationProperties ,但是殺死循環依賴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM