代码之家  ›  专栏  ›  技术社区  ›  Carlos

有Form.BeginInvoke的缩写吗?

  •  4
  • Carlos  · 技术社区  · 14 年前

    在我的GUI代码中,我经常这样写:

    private void SecondTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (progressBar1.InvokeRequired)
        {
          progressBar1.BeginInvoke(new ElapsedEventHandler(SecondTimer_Elapsed), new[] {sender, e});
          return;
        }
    //Code goes here
    }
    

    当然,如果应用程序是多线程的,这是必需的,因为我们需要整理最初创建控件的线程。问题是,编写委托并将参数放入数组可能会很麻烦,而且它会占用每个此类事件处理程序顶部的空间。 这些行中是否有属性或其他内容将替换此代码? 基本上是一个标签,上面写着“如果你在错误的线程上,用相同的参数在GUI线程上再次调用我”。

    3 回复  |  直到 14 年前
        1
  •  13
  •   Jon Skeet    14 年前

    我不知道有什么类似的事情,但这可能是一个有用的扩展方法:

    public static class Extensions
    {
        public static void Execute(this ISynchronizeInvoke invoker,
                                   MethodInvoker action)
        {
            if (invoker.InvokeRequired)
            {
                 invoker.BeginInvoke(action);
            }
            else
            {
                 action();
            }
        }
    }
    

    现在这只适用于无参数委托,当然…但对于lambda表达式来说,这不一定是个问题:

    progressBar1.Execute(() => SecondTimer_Elapsed(sender, e));
    

    这有以下优点:

    • 写起来很简单
    • 签名不能出错(你不依赖于后期绑定)
    • MethodInvoker 我相信执行效率比其他代表稍高一点
    • 如果没有太多要执行的代码,可以在lambda表达式中以内联方式编写代码。
        2
  •  3
  •   Rich    14 年前

    您可以使用扩展方法来整理:

    // Extension methods.
    public static void BeginInvoke(this ISynchronizeInvoke @this, MethodInvoker action) {
        if (@this.InvokeRequired) @this.BeginInvoke(action);
        else action();
    }
    
    public static void BeginInvoke<T1, T2>(this ISynchronizeInvoke @this, Action<T1, T2> action, T1 arg1, T2 arg2) {
        if (@this.InvokeRequired) @this.BeginInvoke(action, new object[] { arg1, arg2 });
        else action(arg1, arg2);
    }
    
    // Code elsewhere.
    progressBar1.BeginInvoke(() => SecondTimer_Elapsed(sender, e));
    // Or:
    progressBar1.BeginInvoke(SecondTimer_Elapsed, sender, e);
    

    编辑: JonSkeet说使用MethodInvoker委托更快是正确的。从 MSDN :

    打电话给某人 EventHandler MethodInvoker 委托将比调用其他类型的委托更快。

        3
  •  0
  •   Jan Jongboom    14 年前

    抓住一个 AOP framework 为此。您可以创建一个 MethodInterceptionAspect 当调用函数时激发。然后您可以进行检查,或者将函数(您对函数和它的参数有一个引用)抛给GUI线程,或者直接执行它。

    优点是您必须编写一次此代码,并且只需一个属性就可以将其应用于所需的每个属性。