2012-01-31 69 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