C# 在另一个线程上创建窗体时使用ShowDialog(窗体)?

C# 在另一个线程上创建窗体时使用ShowDialog(窗体)?,c#,winforms,dialog,multithreading,C#,Winforms,Dialog,Multithreading,我有一个像对话框一样使用的表单,为了确保对话框得到正确的父对象,使用了以下方法: this.ShowDialog(myForm); 问题是,这(我的对话框表单)和我的表单是在不同的线程上创建的,当调用ShowDialog时,将抛出一个交叉线程异常 this.InvokeRequired = false myForm.InvokeRequired = true 我该怎么处理?我必须确保这两个表单都是在同一个UI线程上创建的吗?您必须确保所有表单都是在UI线程上创建的 因此,与其在后台线程上创建

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

this.ShowDialog(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()

Chris建议了正确的方法,但只要你现在在这里,你就可以尝试以下方法:

public void ShowMe()
{
 if (_myForm.InvokeRequired)
                _myForm.Invoke(new MethodInvoker(ShowMe));
            else
                this.ShowDialog(_myForm); 
}
如果上述操作不起作用,则将SynchronizationContext从父窗体传递给正在执行ShowDialog的类,并对其执行Invoke


另一方面,您可能需要重新审视您的设计。看起来很复杂

这对我有用-这段代码是在“父”窗体中运行的,它在主线程上运行,子窗体从另一个线程运行,父窗体作为参数传递给另一个线程,因为它以前在主线程上打开过:

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);
    }
在主线程上的父窗体中:

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


希望这有帮助

您在哪个线程上创建表单?这是什么?这是用作对话框的winform。不知道表单和对话框是在哪个线程上创建的,在当前设置中每次都可能不同。这完全取决于创建对话框和myform的控制器。“不知道表单和对话框是在哪个线程上创建的,在当前设置中每次都可能不同。”这就是您的问题所在。这个.ShowDialog();???您是从表单本身启动表单吗?据我所知,在Winforms中有一个GUI线程。表单只能显示在GUI线程上,因此当您显示表单时,它将是一个跨线程调用,因为它将显示在GUI线程上。是的,但这是在对话框表单(this)或myForm上检查所需的调用?在
myForm
上检查它。在您尝试使用
ShowDialog()
>的同一位置,我现在已经尝试了此操作,它会给我相同的交叉线程异常?>已经测试了此操作,它会引发相同的交叉线程异常。我使用WindowsFormsSynchronizationContext.Current将工作放入UI线程。否!常见的误解。您可以在自己的线程中创建任何表单,只要它们在自己的线程中运行。C.f应用程序。运行