Invoking UI Thread Extension Method
In this post I want to demonstrate a great usage of extension methods in C# 3.0.
Most of you are probably aware of the fact that it is not allowed to access a Controls from a thread other than the one in which it was created. The typical solution involves checking the Control’s InvokeRequired property, and in case it’s value is true, calling Invoke (or BeginInvoke), which marshals the call to the Control’s thread.
For example, in case we have a button, which we want to enable or disable from another thread, we’ll typically write the following method:
1: private void SetButtonEnabled(bool enabled)
2: {
3: if (this.InvokeRequired)
4: {
5: MethodInvoker method = () => SetButtonEnabled(enabled);
6: this.Invoke(method);
7: }
8: else
9: {
10: this.btnRunProcess.Enabled = enabled;
11: }
12:
13: }
Note that the method invokes itself in case invoking required.
However, in most situations, we’ll want to update numerous controls from another thread: change progress bar, enable/disable controls, etc… Using the above technique, each operation requires a separate function.
So how about generalizing things, making use of the newest C# 3.0 enhancements? The idea is to create an extension method, that takes a delegate as an argument. Using lambda expressions permits a very nice syntax. Here is the extension method:
1: public static class ControlExtensions
2: {
3: public static void Invoke(this Control control, Action action)
4: {
5: if (control.InvokeRequired)
6: {
7: MethodInvoker method = () => Invoke(control, action);
8: control.BeginInvoke(method);
9: }
10: else
11: {
12: action();
13: }
14: }
15: }
Note that I’ve used the BeginInvoke method to prevent the waiting for the completion. Feel free to change it to Invoke.
And this is a typical usage for this method:
this.Invoke(() => this.progressBar1.Value = 0);
this.Invoke(() => this.progressBar1.Visible = true);
this.Invoke(() => this.btnRunProcess.Enabled = false);
I don’t think it is an extremely new idea, and I guess some of you are already using some similar technique. However, my goal in this post was to show you a great usage of extension methods. While I predict this C#3.0 enhancement to be the most over-abused one, there are many great usages that can make our life much simpler.
This is a sample application that shows a usage of the above method for a long running process that runs using BackgroundWorker:
Have fun.