我有一个像对话框一样使用的表单,以确保对话框获得正确的父对象使用以下方法:
this.ShowDialog(myForm);
问题是这个(我的对话框形式)和myForm是在不同的线程上创建的,当调用ShowDialog时会抛出一个crossthread异常。
this.InvokeRequired = false
myForm.InvokeRequired = true
我该如何处理?我是否必须确保两者都在同一个UI线程上创建?
答案 0 :(得分:4)
您必须确保在UI线程上创建所有表单。
因此,不是在后台线程上创建表单,而是将消息传递给UI线程,告诉它创建并显示表单。
答案 1 :(得分:1)
包含自解释变量的示例代码:
var logicToInvokeInsideUIThread = new MethodInvoker(() =>
{
// ...
ShowDialog(this);
// ...
};
if (InvokeRequired)
{
Invoke(logicToInvokeInsideUIThread);
}
else
{
logicToInvokeInsideUIThread.Invoke();
}
我想这是处理此类情况的更好的代码逻辑。有时候不需要Invoke()
。
答案 2 :(得分:1)
克里斯提出了正确的方法,但只要你现在就在这里,你可以试试这个:
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
在相关的说明中,您可能希望重新审视您的设计。看起来很复杂。
答案 3 :(得分:0)
这对我有用-此代码是在主线程上运行的“父”表单中,子表单是从另一个线程中运行的,父表单作为参数传递给了另一个线程先前已在主线程上打开:
在主线程的父窗体中:
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,我也可以从另一个线程创建并访问表单!
希望有帮助