This is a cross-cutting concern, no? I do this with the following extension methods:
public static void InvokeOnUIThread( this Control myControl, Action action );
public static void InvokeOnUIThread<T>( this Control myControl, Action<T> action, T parameter );
which would be used as follows:
this.InvokeOnUIThread( () => myControl.Text = "Keyboard acquired" );
Asked for feeback on this earlier...what do you guys think?