Form.BeginInvoke有简写吗?

时间:2010-08-15 20:50:35

标签: c# .net winforms attributes syntactic-sugar

我的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线程上再次使用相同的args调用我。“

3 个答案:

答案 0 :(得分:13)

我不知道有什么相似的东西,但这对你来说可能是一个有用的扩展方法:

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表达式
  • 中内联编写

答案 1 :(得分:3)

你可以用扩展方法整理一下:

// 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);

编辑:Jon Skeet说使用MethodInvoker委托更快。来自MSDN

  

EventHandlerMethodInvoker代表的调用将比调用其他类型的代理更快。

答案 2 :(得分:0)

为此获取AOP framework。您可以创建在调用函数时触发的MethodInterceptionAspect。然后你可以做检查,然后将函数(你有一个函数及其参数的引用)扔到GUI线程,或者直接执行它。

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