I would let the business object fire an event to be caught by the view ( UI ) and do the marshaling on that event handler, so you have in that place a Control
to understand if an invoke is needed or not:
public static class ControlExtentions
{
public delegate void InvokeHandler();
public static bool SafeInvoke(this Control control, InvokeHandler handler)
{
if (control.InvokeRequired)
{
try
{
control.Invoke(handler);
}
finally { }
return false;
}
else
handler.Invoke();
return true;
}
}
if you are using WPF, you can take inspiration from CaliburnMicro:
public static class Execute
{
private static Action<System.Action> executor = action => action();
/// <summary>
/// Initializes the framework using the current dispatcher.
/// </summary>
public static void InitializeWithDispatcher()
{
#if SILVERLIGHT
var dispatcher = Deployment.Current.Dispatcher;
executor = action => {
if(dispatcher.CheckAccess())
action();
else {
var waitHandle = new ManualResetEvent(false);
Exception exception = null;
dispatcher.BeginInvoke(() => {
try {
action();
}
catch(Exception ex) {
exception = ex;
}
waitHandle.Set();
});
waitHandle.WaitOne();
if(exception != null)
throw new TargetInvocationException("An error occurred while dispatching a call to the UI Thread", exception);
}
};
#else
var dispatcher = Dispatcher.CurrentDispatcher;
executor = action => {
if(dispatcher.CheckAccess())
action();
else dispatcher.Invoke(action);
};
#endif
}
/// <summary>
/// Resets the executor to use a non-dispatcher-based action executor.
/// </summary>
public static void ResetWithoutDispatcher() {
executor = action => action();
}
/// <summary>
/// Executes the action on the UI thread.
/// </summary>
/// <param name="action">The action to execute.</param>
public static void OnUIThread(this System.Action action) {
executor(action);
}
}