System.Threading.SynchronizationContext.Current.Post(theMethod, state); delegate UiSafeCall(delegate d, params object p); void SomeUiSafeCall(delegate d, params object p) { if (InvokeRequired) BeginInvoke(d,p); else { //do stuff to UI } } delegate UiSafeCall(delegate d, params object p); void SomeUiSafeCall(delegate d, params object p) { if (this.InvokeRequired) this.BeginInvoke(d,p); else { //do stuff to UI } } public class MyBackgroundThread : BackgroundWorker { public event EventHandler IWantTheUIToDoSomething; public MyStatus TheUIWantsToKnowThis { get { whatever... } } public void TheUIWantsMeToDoSomething() { // Do something... } protected override void OnDoWork(DoWorkEventArgs e) { // This is called when the thread is started while (!CancellationPending) { // The UI will set IWantTheUIToDoSomething when it is ready to do things. if ((IWantTheUIToDoSomething != null) && IHaveUIData()) IWantTheUIToDoSomething( this, new ClassToPassToUI(uiData) ); } } } public partial class MyUIClass : Form { MyBackgroundThread backgroundThread; delegate void ChangeUICallback(object sender, ClassToPassToUI uiData); ... public MyUIClass { backgroundThread = new MyBackgroundThread(); // Do this when you're ready for requests from background threads: backgroundThread.IWantTheUIToDoSomething += new EventHandler(SomeoneWantsToChangeTheUI); // This will run MyBackgroundThread.OnDoWork in a background thread: backgroundThread.RunWorkerAsync(); } private void UserClickedAButtonOrSomething(object sender, EventArgs e) { // Really this should be done in the background thread, // it is here as an example of calling a background task from the UI. if (backgroundThread.TheUIWantsToKnowThis == MyStatus.ThreadIsInAStateToHandleUserRequests) backgroundThread.TheUIWantsMeToDoSomething(); // The UI can change the UI as well, this will not need marshalling. SomeoneWantsToChangeTheUI( this, new ClassToPassToUI(localData) ); } void SomeoneWantsToChangeTheUI(object sender, ClassToPassToUI uiData) { if (InvokeRequired) { // A background thread wants to change the UI. if (iAmInAStateWhereTheUICanBeChanged) { var callback = new ChangeUICallback(SomeoneWantsToChangeTheUI); Invoke(callback, new object[] { sender, uiData }); } } else { // This is on the UI thread, either because it was called from the UI or was marshalled. ChangeTheUI(uiData) } } }