Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 设置WinForms.Form owner时出现跨线程异常-如何正确操作?_C#_Winforms_Invoke - Fatal编程技术网

C# 设置WinForms.Form owner时出现跨线程异常-如何正确操作?

C# 设置WinForms.Form owner时出现跨线程异常-如何正确操作?,c#,winforms,invoke,C#,Winforms,Invoke,我有一个主UI线程,它运行应用程序并创建主窗口窗体(我们称之为W)。我还有一个辅助线程,我启动它并创建一个对话框(我们称之为B) 我想将对话框B的所有者设置为主窗口W。Bs所有者的设置发生在创建B的线程上。基本上: b.Owner = w; 但这会引发一个跨线程异常,告诉我我试图从错误的线程访问W对象 因此,我尝试在主UI线程上使用控件执行代码。在W上调用。但是,我收到了相同的错误,告诉我我试图从错误的线程访问B: System.InvalidOperationException was un

我有一个主UI线程,它运行应用程序并创建主窗口窗体(我们称之为
W
)。我还有一个辅助线程,我启动它并创建一个对话框(我们称之为
B

我想将对话框
B
的所有者设置为主窗口
W
B
s所有者的设置发生在创建
B
的线程上。基本上:

b.Owner = w;
但这会引发一个跨线程异常,告诉我我试图从错误的线程访问
W
对象

因此,我尝试在主UI线程上使用
控件执行代码。在
W
上调用
。但是,我收到了相同的错误,告诉我我试图从错误的线程访问
B

System.InvalidOperationException was unhandled by user code
  Message=Cross-thread operation not valid: Control 'B' accessed from a
  thread other than the thread it was created on.
  Source=System.Windows.Forms

我应该怎样做才对呢?

B
需要在UI线程上创建


您仍然可以通过使用
控件从次线程与
B
进行交互。如果您在不同的线程上实际运行两个消息循环,则无法执行所需的操作。如果你想拥有
B
,你必须在主线程上创建
B
,并从第二个线程调用
B
的所有交互。

这是Winforms中的一个小错误,Windows实际上支持使所有者成为在另一个线程上创建的窗口。有一种方法可以禁用该检查,这是你永远不应该做的。除非你不得不这么做,我想:

    private void button1_Click(object sender, EventArgs e) {
        var t = new Thread(() => {
            Control.CheckForIllegalCrossThreadCalls = false;
            var frm = new Form2();
            frm.Show(this);
            Control.CheckForIllegalCrossThreadCalls = true;
            Application.Run(frm);
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

我不知道这是否100%安全,可能有Winforms交互会把事情搞砸。您在未经测试的水域,到处都是线程鲨鱼。

不要在多线程上使用表单。这会给你带来更多的麻烦。你读过这篇文章吗?如果这对您没有帮助,您应该发布导致错误的代码。也许您可以告诉我们您希望利用的所有权功能(希望不是所有功能),我们可以建议实现类似效果的方法?感谢所有发布者;我知道我是在自找麻烦。我需要在主UI线程上运行一些遗留代码,并且我希望有一个进度对话框来显示这一过程;我不能让主UI线程处理进度对话框。因此,我选择了一个由另一个线程100%管理的进度对话框。在我的情况下,它不适用于我想要做的事情:如果主UI线程被阻止工作,我的
B
窗口将不会更新。你的建议很有趣。在我的例子中,我可以确保显示对话框的代码不会干扰主UI线程。我来试试。关于上述方法的安全性,你有进一步的了解吗?我想这样做(让一个表单拥有一个绑定到不同线程的表单),但需要考虑两个问题:(1)显示另一个表单拥有的表单将调用
Owner.AddOwnedForm
,这可能不是线程安全的;最好在所有者窗体的线程上执行操作;(2) 如果绑定到不同线程的两个窗体试图同时显示它们自己,则其中一个窗体可能会在另一个窗体将其设置为false和执行要求其为false的操作之间设置
CheckForIllegalCrossThreadCalls=true
。显然存在另一个解决方案,将父进程的
.Handle
作为参数传递给线程的过程,并在过程内部从该句柄传递给
.Show()
。然后无需关闭
检查非法CrossThreadCalls