2012-11-06 18 views
1

鉴于使用2种表单时是否需要两次单独的InvokeRequired检查?

Action closeLoadingAction = new Action(() => 
{ 
    loadingForm.Close(); 
    #region - may need to put into second Action 
    panelOnMainForm.Controls.AddRange(physdocControls.ToList<Control>().ToArray()); 
    if (Handle != IntPtr.Zero) 
    User32DLL.SetForegroundWindow(this.Handle);//Handle is a property of the mainForm. 
    #endregion 
}); 

有时我得到把手不创建的异常,即使我检查所需的调用。

if(loadingForm.InvokeRequired) 
    loadingForm.Invoke(closeLoadingAction); 
else 
    closeLoadingAction(); 

加载表单与主窗体在相同的线程上运行。您在上面看到的代码运行在单独的线程中。我怀疑我需要另一个检查来调用主窗体。我需要再次检查还是我已经安全?

+0

'Handle'从哪里来,这是在控制中运行吗?控件是否已创建(有句柄可用)?还有一种方便的扩展方法可以减少表单控件上的InvokeRequired检查冗余,但这是一个不同的故事。 –

+0

@QuintinRobinson - 已更新的问题。详细的事情会很好......我在我的代码中使用了很多次。 –

+1

WRT的扩展方法:看看这个答案http://stackoverflow.com/a/12179408/12707如果你是如此的倾向,你可以改变签名为'Action'而不是'MethodInvoker',但应该按原样工作。 –

回答

2

你看到上面的代码在一个单独的线程

使用InvokeRequired这样运行时,你知道这些代码在另一个线程上运行是一个坏的反模式。你可以用它做更多有用的事情。像:

if (!loadingForm.InvokeRequired) { 
    throw new InvalidOperationException("Threading race detected"); 
} 
loadingForm.Invoke(closeLoadingAction); 

或者,如果你的意思是启动加载线程加载窗体的Load事件被炒了鱿鱼更实用的一个:

while (!loadingForm.InvokeRequired) Thread.Sleep(50); 
loadingForm.Invoke(closeLoadingAction); 

或者只是做正确的方式有如下形式的Load事件启动线程。

1

如果在您尝试Invoke委托之前表单未显示或已关闭,您应该只获取那些“未创建句柄”异常。没有足够的代码来确定是否是这种情况,所以如果我在你的鞋子里,我会试着确定是否在方法被调用之前调用加载表单(因为这是调用者)。

因为两个表单都在同一个线程上,所以只需检查加载表单的InvokeRequired属性即可安全。尽管一般情况下,如果您要在主窗体上操作,您应该检查该窗体的InvokeRequired属性。同样,如果您要在装货单上操作(例如上面的电话号码Close),您应该检查装货单的InvokeRequired财产。上面你改变panelOnMainForm,所以我会检查这是完全安全的,但我不认为这是必要的。

+0

错误必须来自某件事。我不关闭加载表单。如果加载的MainForm和加载表单没有句柄会怎么样?这不是一个问题吗? –

+0

加载表单在它尚未显示时(仅通过“Show”或“ShowDialog”)或已经关闭(通过“Close”或通过其GUI)时,不会显示句柄_only_。我同意@MrBlue,这是一个种族,但没有足够的代码让我们看看它是如何发生的。 –

1

听起来像是为loadingForm创建的手柄和loadingForm.Close()的呼叫之间的竞赛。

解决此问题的一个方法是在loadingForm.HandleCreated事件触发时启动线程,该线程具有代码.Invoke/.Close

private void loadingForm_HandleCreated(object sender, EventArgs e) 
{ 
    var t = new Thread(DoLoadingStuff); 
    t.Start(); 
} 

private void DoLoadingStuff() 
{ 
    // ... 

    if(loadingForm.InvokeRequired) 
     loadingForm.Invoke(closeLoadingAction); 
    else 
     closeLoadingAction(); 
} 
相关问题