我有一个像对话框一样使用的表单,请确保使用以下方法来使对话框获得正确的父级:
this.ShowDialog(myForm);
问题是,这(我的对话框形式)和myForm是在不同的线程上创建的,并且在调用ShowDialog时,将引发跨线程异常。
this.InvokeRequired = false
myForm.InvokeRequired = true
我该如何处理?我是否必须确保两者都在同一UI线程上创建?
您必须确保所有表单都在UI线程上创建。
因此,不要在后台线程上创建表单,而是将一条消息传递给UI线程以告诉它创建和显示表单。
带有自解释变量的示例代码:
var logicToInvokeInsideUIThread = new MethodInvoker(() =>
{
// ...
ShowDialog(this);
// ...
};
if (InvokeRequired)
{
Invoke(logicToInvokeInsideUIThread);
}
else
{
logicToInvokeInsideUIThread.Invoke();
}
我想这是处理这种情况的更好的代码逻辑。有时不需要Invoke()
。
克里斯建议了正确的方法,但是只要您现在就在这里,就可以尝试以下方法:
public void ShowMe()
{
if (_myForm.InvokeRequired)
_myForm.Invoke(new MethodInvoker(ShowMe));
else
this.ShowDialog(_myForm);
}
如果上述方法不起作用,则将SynchronizationContext从您的父窗体传递给执行ShowDialog的类,并在该类上执行Invoke。
http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx
关于相关说明,您可能希望重新审视您的设计。似乎很令人费解。
这对我有用-该代码是在主线程上运行的“父”表单中,子表单从另一个线程中运行,父表单作为参数传递给了另一个线程,因为它已经先前在主线程上打开过:
在主线程的父表单中:
public delegate void ShowChildConsumer(Form ChildForm);
public void ShowChild(Form ChildForm)
{
if (this.InvokeRequired)
{
var d = new ShowChildConsumer(ShowChild);
this.Invoke(d, new object[] { ChildForm });
}
else
ChildForm.ShowDialog(this);
}
在另一个线程中:
frmChildForm childform = new frmChildForm();
parentform.ShowChild(childform);
result = childform.DialogResult;
childform.Dispose();
有趣的是,即使在主线程上调用了ShowDialog,我也可以从另一个线程创建和访问表单!
希望有所帮助