There is no universal “best” way to work with threads. I'm afraid you just need to try different ways to do something.
I especially like the continuation idea of Jeremy D. Miller described on this page (scroll down to find the "continuation" section). It is really elegant and means very little coding.
Basically, when you call "ExecuteWithContinuation" with the Func argument, the function executes asynchronously, and then returns the action when it ends. The action is then transferred back to your UI thread to act as a continuation. This allows you to quickly split your operations into two bits:
- Perform a lengthy operation that should not block the user interface
- ... when done, update the user interface in the user interface thread.
It takes some getting used to, but it's pretty cool.
public class AsyncCommandExecutor : ICommandExecutor { private readonly SynchronizationContext m_context; public AsyncCommandExecutor(SynchronizationContext context) { if (context == null) throw new ArgumentNullException("context"); m_context = context; } public void Execute(Action command) { ThreadPool.QueueUserWorkItem(o => command()); } public void ExecuteWithContinuation(Func<Action> command) { ThreadPool.QueueUserWorkItem(o => { var continuation = command(); m_context.Send(x => continuation(), null); }); } }
Then you should use it like this (forgive formatting ...)
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished() { DisableUi(); m_commandExecutor.ExecuteWithContinuation( () => { // this is the long-running bit ConnectToServer(); // This is the continuation that will be run // on the UI thread return () => { EnableUi(); }; }); }
source share