C# Form.BeginInvoke有速记吗?
在我的GUI代码中,我经常编写如下内容:C# Form.BeginInvoke有速记吗?,c#,.net,winforms,attributes,syntactic-sugar,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; }
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线程上再次调用我。”我不知道有什么类似的东西,但这可能是一种有用的扩展方法:
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表达式中内联编写
优点是您必须编写此代码一次,并且只需一个属性即可将其应用于所需的每个属性。您可以使用扩展方法来整理此代码:
// 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);
//扩展方法。
公共静态void BeginInvoke(这是SynchronizeInvoke@this,MethodInvoker操作){
如果(@this.InvokeRequired)@this.BeginInvoke(操作);
else动作();
}
公共静态void BeginInvoke(这是synchronizeinvoke@this,Action-Action,T1 arg1,T2 arg2){
if(@this.InvokeRequired)@this.BeginInvoke(操作,新对象[]{arg1,arg2});
else操作(arg1、arg2);
}
//代码在别处。
progressBar1.BeginInvoke(()=>SecondTimer_已过(发送方,e));
//或:
progressBar1.BeginInvoke(第二个计时器已过,发送方,e);
编辑:Jon Skeet说使用MethodInvoker委托更快是正确的。从:
调用EventHandler
或MethodInvoker
委托将比调用其他类型的委托更快