2012-01-31 72 views
0

當某些表單中存在長時間運行的代碼(例如,數據加載期間)時,我在其他線程上顯示等待表單(說「請稍候...」)。我給這樣的形式:Control.Invoke錯誤:句柄尚未創建

m_PopProcessingThread = New Thread(New ThreadStart(
    Sub() 
     m_PopProcessingForm = New WaitingForm(m_Message) 
     Application.Run(m_PopProcessingForm) 
    End Sub)) 
m_PopProcessingThread.Name = "Pop Processing Thread" 
m_PopProcessingThread.SetApartmentState(ApartmentState.STA) 
m_PopProcessingThread.Start() 

然後,我隱藏它是這樣的:

While m_PopProcessingForm Is Nothing OrElse Not m_PopProcessingForm.IsHandleCreated 
    Threading.Thread.Sleep(20) 'Wait a bit for the form to be created 
End While 
' Dispose of the pop processing form (by disposing of this form, thread is also exited) 
m_PopProcessingForm.Invoke(Sub() 
           m_PopProcessingForm.Dispose() 
          End Sub) 

此代碼的偉大工程,但我剛接到一個顧客的bug報告:

Exception Type : System.InvalidOperationException 
Invoke or BeginInvoke cannot be called on a control until the window handle has been created. 
    at System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle) 
    at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) 
    at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) 
    at System.Windows.Forms.Control.Invoke(Delegate method) 

堆棧跟蹤指向隱藏表單的代碼部分。在Invoke調用之前,如何創建句柄?我循環直到創建句柄?謝謝你的幫助。

+0

使用一個BackgroundWork和/或任務它們正是爲此目的而設計的。 – 2012-01-31 19:07:03

+0

我知道這有點顛倒,通常應該是在另一個線程,而不是等待的形式。但考慮到目前的代碼在99,999%的時間內工作,我寧願修復它,而不是改變我的所有代碼。 – 2012-01-31 19:13:03

回答

2

表單在您的IsHandleCreated檢查之後但調用Dispose之前可能已關閉。用戶可能點擊了[x]或在表單上按下了Ctrl-F4。

+0

這將是令人驚訝的,在此表單上沒有X按鈕,並且表單不會長時間保持打開狀態。 – 2012-01-31 19:08:24

+0

我想這個錯誤可能是通過按Alt-F4發生的,但是如果表單在IsHandleCreated和Invoke指令之間關閉,考慮到它們之間相互關聯,那將是非常令人驚訝的。 – 2012-01-31 19:23:33

+0

你確實讓我意識到,如果用戶按下Alt-F4可能會出現無限循環,所以非常感謝! – 2012-01-31 19:24:25