C# 如何从另一个线程中的窗体关闭新线程中的窗体?

C# 如何从另一个线程中的窗体关闭新线程中的窗体?,c#,winforms,C#,Winforms,在过去的一天左右,我一直在想这个问题 我有一个包含Form1的程序,还有一个在新线程中生成Form2的按钮 我在Form1上还有一个按钮可以关闭Form2,但是因为Form2在另一个线程中,我不能直接触摸那个对象 我可以执行t.Abort(),但这会引发异常 我怎样才能优雅地触摸另一根线?对它做些什么 例如,如何从Form1中关闭表单 我在谷歌上搜索了“如何从另一个线程中关闭表单”,并找到了几个提示Invoke和Delegate的链接,但在尝试了一些东西之后,我显然不知道如何正确使用它 有谁能帮

在过去的一天左右,我一直在想这个问题

我有一个包含Form1的程序,还有一个在新线程中生成Form2的按钮

我在Form1上还有一个按钮可以关闭Form2,但是因为Form2在另一个线程中,我不能直接触摸那个对象

我可以执行
t.Abort()
,但这会引发异常

我怎样才能优雅地触摸另一根线?对它做些什么

例如,如何从Form1中关闭表单

我在谷歌上搜索了“如何从另一个线程中关闭表单”,并找到了几个提示Invoke和Delegate的链接,但在尝试了一些东西之后,我显然不知道如何正确使用它

有谁能帮助我理解它将如何应用到我的代码中,以便我理解如何使用它们?在哪种情况下,等等

为了方便您,我已将项目上载到github:

--

代码:

[表格1.cs]

    public void FormThread()
    {
        Application.Run(new Form2());
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(new ThreadStart(FormThread));
        t.Start();
    }

    private void button2_Click(object sender, EventArgs e)
    {

        //Need to close Form2 from here.

    }
[表格2.cs]


有另一个表单代码。

一般来说,两个表单有两个线程不是一个好主意。将所有表单放在主UI线程上,并将逻辑和工作转移到后台线程上,这几乎总是一个更好的主意

也就是说,如果表单在单独的线程中运行,您应该能够使用
BeginInvoke
关闭它:

 otherForm.BeginInvoke(new Action(() => otherForm.Close()));

编辑:

在您的情况下,您需要保存实例:

Form2 otherForm;
public void FormThread()
{       
    otherForm = new Form2();
    Application.Run(otherForm);
}

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(FormThread));
    t.SetApartmentState(ApartmentState.STA); // THIS IS REQUIRED!
    t.Start();
}

private void button2_Click(object sender, EventArgs e)
{
    //Need to close Form2 from here.
    if (otherForm != null)
    {
       otherForm.BeginInvoke(new Action( () => otherForm.Close() ));
       otherForm = null;
    }
}

不要使用多LPE UI线程。别这样。它会让你的生活陷入地狱,而winforms框架并不是为了支持它而构建的。为你的程序使用一个UI线程。你应该只粘贴你在文章中尝试的代码。我不打算在我的计算机上打开该文件。我无法从工作地点访问GitHub。只需将代码粘贴到创建和启动线程的位置。谢谢,我添加了一些代码。但是如果我启动另一个UI窗口,前一个窗口是“冻结”的,这就是我使用另一个线程的原因。Reed Copsey建议使用Backgroundworker,这是正确的方法吗?@PowerCat如果你阻止你的UI线程进行非UI工作,那么这就是一个问题。您可以通过在非UI线程中执行非UI工作来修复它,而不是创建两个UI线程并阻止一个表单而不是另一个表单。谢谢。我一直在看“其他形式”,但这是我不明白的部分之一。什么是“其他形式”?它如何与代码相匹配?我将查看后台线程。当我键入Form2时,“BeginInvoke”方法不会出现在intellisense上。这个BeginInvoke是我在其他答案上看到的,但是我从来没有在我的代码中实现过。对不起,我不明白。请您指出我要在哪一行,哪一个文件中加上这一行好吗?既然我无法在该事件中添加该命令,我将如何使button2\u Click执行该命令?@PowerCat您需要将
new Form2()
实例保存在某个地方,并有权访问它。@PowerCat为您添加了代码-请注意STA线程调用(您也需要它)