【问题标题】:Multithreading/C#: Can I do a BeginInvoke on multiple UI elements?多线程/C#:我可以在多个 UI 元素上执行 BeginInvoke 吗?
【发布时间】:2011-05-27 23:15:17
【问题描述】:

假设我在一个工作线程上,我想更改几个 UI 元素、一个按钮、一个文本框等。

我需要对每个元素调用 BeginInvoke 吗?即,

  myButton.BeginInvoke(someMethod);
  myTextBox.BeginInvoke(someOtherMethod);

或者有没有办法做一个 BeginInvoke 然后更新多个 UI 元素?谢谢

【问题讨论】:

    标签: c# wpf winforms multithreading


    【解决方案1】:

    只需在表单上调用 BeginInvoke 并从那里更新所有控件。


    @James Black:我的捷径是添加这样的方法:

    private IAsyncResult BeginInvoke(MethodInvoker method) {
        return BeginInvoke((Delegate)method);
    }
    

    然后这样称呼它:

    BeginInvoke(() => {
        txtName.Text = name;
    });
    

    【讨论】:

    • 对一个简单问题的简单回答,谢谢
    • (代表)演员?需要它,因为我正在添加 BeginInvoke(同名)方法的重载,以便调用转到原始的 BeginInvoke 方法,否则它将递归运行新方法并抛出 StackOverflowException。
    【解决方案2】:

    不,这不是必需的。除非您的应用程序正在运行多个消息循环(极不可能,并且您肯定知道它是否存在),否则您调用BeginInvoke 的控件并不重要;它所做的只是将委托和参数传递到一个队列中,该队列作为消息循环的一部分进行处理。严格来说,与之交互的控件与您调用BeginInvoke on 的控件之间不必有任何关系。

    【讨论】:

      【解决方案3】:

      如果您可以使用并行扩展框架,我发现这很有帮助:

      TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

      我在构造函数中执行此操作,所以我在主线程上。

      然后我会打电话给Task 这样做: 私人无效changeElements(){ (新任务(()=> { // 更新用户界面 })).Start(uiScheduler); }

      这样您就可以完成所有您想做的任务,并且在使用BeginInvoke 时删除了很多额外的代码,因为您不再需要委托。

      但是,正如所指出的,您不必调用多个 BeginInvoke 调用来更新 UI,因为在第一个调用之后您已经在主线程上。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-01
        • 1970-01-01
        • 2014-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多