【问题标题】:Close a form from a thread从线程关闭表单
【发布时间】:2012-02-27 17:18:18
【问题描述】:

我有一个以我的主窗体开头的线程

    private void changePasswordbutton_Click_1(object sender, EventArgs e)
    {
        waitForm.Show();
        Thread thread = new Thread(ProcessInkPresenter);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join();
        waitForm.Hide();
        waitForm.Dispose();
    }

我想关闭 ProcessInkPresenter 方法(在线程上运行)中的 waitForm,而不是等待线程完成。

我该怎么做?

谢谢

方法签名

private void ProcessInkPresenter()

在类头中定义

Wait waitForm;

【问题讨论】:

  • stackoverflow.com/a/8443732/555547 会起作用吗?不确定线程​​连接如何影响它。
  • 你为什么在这里使用线程?为什么不直接在其他表单上调用 ShowDialog 呢?
  • 这是一个非常复杂的故事。我需要一个线程来使用 Watin 功能。该线程解析 HTML 以查看密码是否已更改。所以如果成功,我需要让 WaitForm 消失。我们只知道它是否从线程内部成功。我不能在线程内部使用 WaitFoorm.Close,因为 .Net 不允许!

标签: c# .net winforms multithreading c#-4.0


【解决方案1】:

您的原始代码没有意义。它显示一个表单,然后启动一个线程,然后等待该线程完成。如果您希望表单在它自己的 UI 线程上运行,请让 ProcessInkPresenter 在同一个 UI 线程上运行(如果它与 UI 交互,它应该这样做)并关闭表单并在 ProcessInkPresenter 完成时处理掉,试试这个:

private void changePasswordbutton_Click_1(object sender, EventArgs e)
{
    Thread thread = new Thread(state => {
            using (var waitForm = new WaitForm()) {
                waitForm.Activated += (s, e) => {
                    ProcessInkPresenter();
                    waitForm.Hide();
                }
                Application.Run(waitForm);
            }
        }
    );
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
}

如果工作线程不必与 GUI 交互,那么您想要的是如下所示。请注意,我使用 Invoke 来确保与 UI 的交互在 UI 线程上完成。此处无需检查 InvokeRequired,因为我已经确定我在后台线程上。

如果你想保持相同的 waitForm 实例:

private void changePasswordbutton_Click_1(object sender, EventArgs e)
{
    Thread thread = new Thread(state => {
            try {
                ProcessInkPresenter();

                // If ProcessInkPresenter fails, this line will never execute
                waitForm.Invoke(new Action(()=>waitForm.Hide()));
            }
            catch (Exception ex) {
                // You probably want to do something with ex here,
                // rather than just swallowing it.
            }
        });
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    waitForm.Show();
}

注意:如果您有一个 WaitForm 实例(您的 Wait 实例),那么处置您的 WaitForm 是没有意义的。每次使用时都构造一个实例,或者从不释放它并改用.Hide()

【讨论】:

  • 基本上这就是我想要实现的目标。用户单击按钮。我显示一个表单(称为 waitForm)并将其调整为屏幕的宽度和高度。等待表单显示一条消息,而线程执行它自己的事情。如果线程成功完成,我希望 waitForm 消失,只将 ResultForm 留在屏幕上。 (ResultForm 在线程内创建)。
  • 后台进程是否需要以任何方式与GUI交互?
  • 后台进程打开IE,然后开始解析HTML。它与 GUI 没有任何关系。如果结果是肯定的/否定的,我们会启动一个显示结果的新表单。
  • 见我的第二个例子,刚刚添加。
  • 确实如此。我在上面演示的代码将表单的关闭与ProcessInkPresenter 方法的完成联系起来。 如果您的ProcessInkPresenter 没有退出,我的代码怎么可能知道何时关闭表单?
猜你喜欢
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多