我的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调用我。“
答案 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
执行效率略高于其他代表,我相信答案 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:
对
EventHandler
或MethodInvoker
代表的调用将比调用其他类型的代理更快。
答案 2 :(得分:0)
为此获取AOP framework。您可以创建在调用函数时触发的MethodInterceptionAspect
。然后你可以做检查,然后将函数(你有一个函数及其参数的引用)扔到GUI线程,或者直接执行它。
优点是您必须编写一次此代码,并且可以将其应用于仅使用属性所需的每个属性。