代码之家  ›  专栏  ›  技术社区  ›  Matthew Scharley

是否可以使用ISynchronizeInvoke.BeginInvoke()重载线程?

  •  3
  • Matthew Scharley  · 技术社区  · 16 年前

    我有两个线程,我的UI线程和一个工作线程。我的工作线程运行在一个单独的类中,该类由表单实例化,表单将自身作为 ISynchronizeInvoke 到工人类,然后工人类使用 Invoke 在该界面上调用其事件,这些事件向UI提供状态更新以供显示。这真是太棒了。

    我注意到我的后台线程似乎运行缓慢,所以我将调用改为 援引 BeginInvoke

    2 回复  |  直到 16 年前
        1
  •  3
  •   Brann    15 年前

    您肯定是在重载UI线程。

    在第一个示例中,您(在幕后)向UI线程发送消息,等待它被处理(这就是调用的目的,调用最终依赖于 SendMessage ),然后发送另一个。同时,其他消息可能被排队(例如WM_PAINT消息)并被处理。

    在第二个示例中,使用BeginInvoke(它最终依赖于 PostMessage

    您可能提供了太多的状态更新;尽量降低反馈级别。

    如果您想更好地了解消息在windows中的工作方式, this

        2
  •  1
  •   Marc Gravell    16 年前

    一些想法;

    • 尝试批量更新;例如,没有更新的点 每一个 Invoke BeginInvoke
    • 变量捕获;如果您正在使用
    • 使UI更新高效-尤其是 如果 您正在处理一个列表;一些控件(尤其是基于列表的控件)有一对方法,如 BeginEdit / EndEdit End* 被称为

    捕获问题。。。想象一下(工人):

    List<string> stuff = new List<string>();
    for(int i = 0 ; i < 50000 ; i++) {
        stuff.Add(i.ToString());
        if((i % 100) == 0) {
            // update UI
            BeginInvoke((MethodInvoker) delegate {
                foreach(string s in stuff) {
                    listBox.Items.Add(s);
                }
            });
        }
    }
    

    stuff ? UI线程可以在工作线程(一直在运行)经过时对其进行迭代 异步调用 )不断增加。这可能会导致问题。不常 演出

    • 援引 同步运行更新
    • 每次更新创建一个新的缓冲区,这样两个线程就不会有相同的列表实例(不过,您需要非常仔细地查看变量的作用域以确保)
    推荐文章