Is there an abridged version of Form.BeginInvoke?

Quite often, in my GUI, I write something like this:

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

Of course, this is necessary if the application is multi-threaded, since we need to configure the marker on the stream that originally created the control. The fact is that it can be tedious to write a delegate and put the arguments into an array, and it takes up space at the top of each such event handler. Is there any attribute or something like that that will replace this code for you? Basically a shortcut that says: "If you are mistaken, call me again in the GUI thread with the same arguments."

+4
source share
3 answers

I don't know anything like this, but this will probably be a useful way for you to expand:

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

Now this only works for carefree delegates, of course ... but with lambda expressions that shouldn't be a problem:

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

This has the following advantages:

  • Just write
  • You cannot make a mistake with the signature (you do not rely on late binding)
  • MethodInvoker is a little more efficient than other delegates, I believe
  • If you have little code to execute, you can write it in a string in a lambda expression
+13
source

You can remove this using extension methods:

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

Edit: John Skeet is right in saying that using the MethodInvoker delegate is faster. From MSDN :

Invoking an EventHandler or MethodInvoker will be faster than calling another delegate type.

+3
source

Take the AOP framework for this. You can create a MethodInterceptionAspect that fires when the function is called. Then you can perform checks and either transfer the function (you have a link to the function and its arguments) to the GUI thread, or execute it directly.

The advantage is that you will need to write this code once and apply it to each property required only with the attribute.

0
source

All Articles