2013-03-26 53 views
0

今天我注意到我的代碼中有一個錯誤,我想我以前處理過。我正在處理Windows Forms應用程序,我經常使用form_load事件。爲了處理這種情況時出現了錯誤的Form_load事件和異常被拋出我使用下面的代碼:Windows窗體 - 如果form_load事件失敗,使用BeginInvoke

catch (Exception ex) 
{ 
    LogErrorAndShowMessage(ex, Resources.ERROR_LOAD); 

    //Otherwise Error : "Cannot call Close() while doing CreateHandle()". 
    this.BeginInvoke(new InvokeDelegate(CloseTheForm)); 
    LoadForm<Materials>(closeAlreadyOpened : false); 
} 

這就是我如何聲明委託和方法:

public delegate void InvokeDelegate();//used if form load fails 
private void CloseTheForm() 
{ 
    this.Close(); 
} 

它的工作從今天起罰款。發生了什麼 - 在Form_load事件中,我爲我的ComboBoxes設置了DataSource,所以碰巧從SetDataSource方法拋出了一個錯誤,這個錯誤最終與我在使用BeginInvoke - Cannot call Close() while doing CreateHandle()之前得到的錯誤完全相同。

這是例外的行爲,如果從其他地方拋出異常,代碼仍然工作正常,只有在設置數據源期間,我得到了錯誤。

任何建議可能導致這種異常行爲,我該如何解決?

P.S

這是我如何創造新的形式:

protected void LoadForm<T>(ToolStripButton/*ToolStripDropDownButton*/ formButton, 
          string buttonText, 
          long? loadEntityId = null, 
          bool closeAlreadyOpened = true) where T : BaseForm 
{ 
    MainForm parentFrm = GetParentForm(); 

    if (parentFrm != null) 
    { 
     if (formButton != null) 
     { 
      parentFrm.SetForeColor(formButton); 
     } 

     T openForm = SingletonFormProvider.GetInstance<T>(parentFrm, 
                  closeAlreadyOpened); 
     openForm.LoadEntityId = loadEntityId; 
     openForm.MdiParent = parentFrm; 
     openForm.Dock = DockStyle.Fill; 
     openForm.Show(); 
     openForm.Activate(); 
    } 
    else 
    { 
     MessageBox.Show("Parent form not found!", "Error", 
         MessageBoxButtons.OK, MessageBoxIcon.Error); 
    } 
} 

也許作爲提供我應該把try-catchopenForm.Show()各地處理這個問題Hans Passant

+0

這可能是一個愚蠢的問題,但是您可以將代碼從Form_Load方法移動到窗體的構造函數嗎?如果表單沒有顯示/顯示,您將不會遇到處理錯誤... – schglurps 2013-03-26 17:58:40

+0

我沒有真正想過這個。我不確定構造函數是否適合這個。我想這是可能的。 – Leron 2013-03-26 18:00:08

回答

5

Load事件很麻煩。它通常在窗體的Show()方法被調用時觸發。但它可以提前觸發,如果窗體構造函數中的初始化代碼需要創建本機窗口。由於表單對象尚未完全初始化,因此相當不健康。通過在Load事件處理程序中設置一個斷點並查看調試程序的Call Stack窗口,您總是可以找到代碼的作用。

一般而言,您應該避免使用Load事件,只有在需要知道窗口實際大小的罕見情況下才需要。其他所有東西都屬於構造函數,就像使用常規的.NET類一樣。你需要做一些關於捕獲和記錄異常的事情,這最好是用類工廠完成的。樣板工廠可能看起來像這樣:

public static Form1 CreateInstance() { 
     try { 
      var frm = new Form1(); 
      frm.Show(); 
      return frm; 
     } 
     catch (Exception ex) { 
      LogErrorAndShowMessage(ex); 
      return null; 
     } 
    } 
+0

謝謝,我希望你能出現。其實我有這樣的課,請看看編輯帖子,並告訴你這是否會奏效。 – Leron 2013-03-26 17:56:19

+0

好吧,顯然你已經有了一個處理構造函數拋出的異常的好地方。因此,只需將Load事件處理程序中的代碼移出構造函數即可。 – 2013-03-26 18:02:18

+0

謝謝。非常感謝。 – Leron 2013-03-26 18:05:26