使用ShowDialog(form)在另一个线程上创建表单?

时间:2011-11-24 11:42:06

标签: c# winforms dialog multithreading

我有一个像对话框一样使用的表单,以确保对话框获得正确的父对象使用以下方法:

this.ShowDialog(myForm);

问题是这个(我的对话框形式)和myForm是在不同的线程上创建的,当调用ShowDialog时会抛出一个crossthread异常。

this.InvokeRequired = false
myForm.InvokeRequired = true

我该如何处理?我是否必须确保两者都在同一个UI线程上创建?

4 个答案:

答案 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,我也可以从另一个线程创建并访问表单!

希望有帮助