Tuesday, February 15, 2011

InvokeIfRequired

Windows Forms does not allow controls to be accessed from non GUI threads. You are supposed to use the Control.Invoke method that takes a delegate as parameter which I don't find very comfortable.

Here is a simple class with two extension methods that allow you to use a Func<T> or Action as parameter.
   public static class ControlExtensions   
   {  
     public static void InvokeIfRequired(this Control control, Action action)  
     {  
       if (control.InvokeRequired)  
       {  
         control.Invoke(action);  
         return;  
       }  
       action();  
     }  
     public static TResult InvokeIfRequired<TResult>(this Control control, Func<TResult> func)  
     {  
       if (control.InvokeRequired)  
       {  
         return (TResult)control.Invoke(func);  
       }  
       return func();  
     }  
   }  

With these you can write methods like the ones below that can be called by the GUI thread or any other thread.

1. Action
     public void SetLoadingMessage()  
     {  
       this.InvokeIfRequired(() =>   
       {  
         this.labelMessage.Text = "Loading...";  
         this.labelMessage.Visible = true;  
       });  
     }  

2. Func<T>
     public string GetText()  
     {  
       return this.InvokeIfRequired(() => this.textBox.Text);  
     }  

Warning! These methods will throw an exception if the control was diposed.

No comments:

Post a Comment