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

问题描述 投票:2回答:4

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

this.ShowDialog(myForm);

问题是,这(我的对话框形式)和myForm是在不同的线程上创建的,并且在调用ShowDialog时,将引发跨线程异常。

this.InvokeRequired = false
myForm.InvokeRequired = true

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

c# winforms dialog multithreading
4个回答
4
投票

您必须确保所有表单都在UI线程上创建。

因此,不要在后台线程上创建表单,而是将一条消息传递给UI线程以告诉它创建和显示表单。


1
投票

带有自解释变量的示例代码:

var logicToInvokeInsideUIThread = new MethodInvoker(() =>
{
    // ...

    ShowDialog(this);

    // ...
};

if (InvokeRequired)
{
    Invoke(logicToInvokeInsideUIThread);
}
else
{
    logicToInvokeInsideUIThread.Invoke();
}

我想这是处理这种情况的更好的代码逻辑。有时不需要Invoke()


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

关于相关说明,您可能希望重新审视您的设计。似乎很令人费解。


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

希望有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.