Elegantly Invoking
Anyone who has seen code written by me that requires the invoking of WinForm controls will know that I have an irrational hatred of the “recommended” way of resolving cross-thread operations.
Now, whilst I agree that cross-thread operations should be handled correctly, and I’m actually glad Microsoft decided to tighten its belt over this when it came to creating the dotNet framework, it just seems very “bloaty” to have to write methods such as the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 | delegate void SetFirstNameTextCallBack(string value);
private void SetFirstNameText(string value)
{
if (txtFirstName.InvokeRequired)
{
SetFirstNameTextCallBack cb = new SetFirstNameTextCallBack(SetFirstNameText);
cb.Invoke(value);
}
else
{
txtFirstName.Text = value;
}
} |
Ok, you can get a bit cleverer and write delegates and methods that expect a control, property name and property value to be provided, such as this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | delegate void SetControlPropertyCallBack(Control control, string property, object value);
private void SetControlProperty(Control control, string property, object value)
{
if (control.InvokeRequired)
{
SetControlPropertyCallBack cb = new SetControlPropertyCallBack(SetControlProperty);
cb.Invoke(control, property, value);
}
else
{
Type t = control.GetType();
System.Reflection.PropertyInfo propInf = t.GetProperties().First(p => p.Name.ToUpper() == property.ToUpper());
propInf.SetValue(control, value, null);
}
} |
But it still looks yuck to me.
Over the last few weeks, I’ve been increasingly using lambda and extension methods, and came up with a new way of handling invokes that I actually like!
It involves extending the “Invoke” method, as shown below:
1 2 3 4 5 6 7 8 9 10 11 | public static TResult Invoke(this T controlToInvokeOn, Func codeToInvoke) where T : Control
{
if (controlToInvokeOn.InvokeRequired)
{
return (TResult)controlToInvokeOn.Invoke(codeToInvoke);
}
else
{
return (TResult)codeToInvoke();
}
} |
With this implemented, any time you need to invoke anything, you can do so quickly and elegantly with a little lambda:
1 | txtFirstName.Invoke(()=>Text = "test"); |
July 7th, 2009 at 2:13 am
Hello. I think the article is really interesting. I am even interested in reading more. How soon will you update your blog?
July 10th, 2009 at 12:36 am
I want to update it at least once a day, but until I get all the kinks worked out and actually get used to blogging, it may only be once every couple of days :/
but thanks for dropping by!