【问题标题】:how to update a windows form GUI from another class?如何从另一个类更新 Windows 窗体 GUI?
【发布时间】:2010-07-12 06:21:31
【问题描述】:

如何从另一个创建 GUI 但不在创建线程中的类更新 win 表单控件(例如标签、进度条)? (例如 Program.cs 的事件处理程序)

我发现了几篇关于使用 Invoke() 方法从另一个线程更新 GUI 的帖子,但到目前为止我发现的内容只有在代码与表单编写在同一类中时才有效

http://www.yoda.arachsys.com/csharp/threads/winforms.shtml

【问题讨论】:

    标签: c# winforms multithreading


    【解决方案1】:

    您需要在表单上调用Invoke 方法。例如:

    private void someMethod() {
        myOtherForm.Invoke(new MethodInvoker(delegate() {
            // update things in myOtherForm here
        }));
    }
    

    如果您不需要在返回方法之前完成更新,您应该使用BeginInvoke 而不是Invoke

    【讨论】:

    • @Amir:其余代码的外观取决于您的应用程序的结构。本质上,您需要引用要对其执行某些操作的其他控件,并且当您要执行操作时,请在传递给Invoke 的委托中执行操作。具体如何操作取决于您正在编写的应用程序的结构,因此我无法为您提供任何进一步的指导。
    【解决方案2】:

    嗯,这里有两个不同的问题:

    • 从不同的类更新 UI
    • 从其他线程更新 UI

    两者几乎完全正交。单独解决每个问题后,您可以将两者放在一起。

    如果有很好理解的方式需要更改 UI(例如更新状态栏中的文本或类似的东西),我会在 UI 类本身中编写方法来执行此操作,然后调用这些方法从另一个班级。或者,您可以公开 UI 的单个控件 - 最好通过属性 - 然后以正常方式从其他类使用 Control.Invoke,例如

    MethodInvoker action = () => form.StatusLabel.Text = "Finished";
    form.BeginInvoke(action);
    

    只要您调用Invoke 的控件,该控件与您触摸的所有控件“存在”在同一线程上,您使用哪一个都没有关系...因此替代方案可能是:

    Label label = form.StatusLabel;
    MethodInvoker action = () => label.Text = "Finished";
    label.BeginInvoke(action);
    

    这里的一个区别是,在后面的代码中,StatusLabel 属性正在工作线程中进行评估 - 如果您的 UI 将其更改为引用不同的标签,这可能会导致竞争条件在不同的时间。我通常更喜欢第一种方法。

    (顺便说一句,我同意 icktoofay 关于 BeginInvoke 更可取的评论,除非你真的需要等待……尽管你确实需要小心对匿名函数捕获的任何变量的更改。)

    【讨论】:

    • @Amir:如果没有更多关于确切您不了解的内容的详细信息,我真的无法提供任何帮助。
    • 我不知道:我如何使用MethodInvokerBeginInvoke
    • @Amir:我已经向您展示了您如何使用它们。我已经给出了示例代码。
    • 我怎样才能公开对 UI 的控制,然后在其他类中使用 Control.Invoke
    • @Amir:听起来你应该问一个新的详细问题,而不是在我不得不猜测上下文的情况下尝试在 cmets 中完成所有问题。
    猜你喜欢
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 2020-07-13
    相关资源
    最近更新 更多