| « Sympl: an example of language implementation using the DLR | Scrum Coffee (Paris, 11 février) » |
Syntactic sugar for multi-threading in Windows Forms
Today I'm sharing bits of code that we found useful while working on Windows Forms UI code with my customer.
In .Net, the "BackgroundWorker":http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx provides a nice way to handle out-of-UI thread work while being able to report some progress on the UI side.
Sometimes though, we felt that we wanted something more flexible for our needs, and came up with that:
The reverse is also possible:
You'll notice that we don't pass arguments nor return value unlike other kind of sugars for that (see resources below).
That's because we use lambda's all over the place for that, so what would be parameters and return values can be accessed in the lambda's parent scope directly.
That's what works for us. Now to you: what kind of sugar do you use when dealing with threads in Windows Forms ?
h3. Resources
A few links that you may find useful if you target this kind of subject:
* "old yet very detailed informations on Invoke/BeginInvoke stuff":http://weblogs.asp.net/justin_rogers/pages/126345.aspx
* the "BackgroundWorker":http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx provides convenient sugar to handle cancellable worker thread, with ability to report progress
* "Safe ControlInvoke with Lambda's":http://dotnet.org.za/virtualstaticvoid/archive/2009/01/24/safe-controlinvoke-with-lambda-s.aspx covers a larger number of cases than what's presented here
* "Delegate Marshaler":http://thevalerios.net/matt/2008/07/controlinvokerequired-delegatemarshaler-and-anonymous-methods/ - another way of handling these
* "Safe, Even Simpler Multithreading in Windows Forms 2.0":http://www.mikedub.net/mikeDubSamples/SafeReallySimpleMultithreadingInWindowsForms20/SafeReallySimpleMultithreadingInWindowsForms20.htm - pretty good introduction to UI threading
* "Magic":http://gist.github.com/thbar/magic/tree/master - an IronRuby gem focusing on making it easier to create WPF, Silverlight and Windows Forms stuff from IronRuby (more on that later)
5 comments
The InUIThread is a nice extension method but on the other hand I find the InWorkerThread a bit icky, especially the busy wait on worker.IsBusy. Yes, the DoEvents will process Windows messages, but otherwise If the purpose is to have only one worker thread worker, you could have a wait on a waithandle. If you want to simply fire and forget and let the threadpool do its trick, why wait for completion in the first place?
yeah we share your feelings on InWorkerThread. It feels a bit weird.
The use case behind that is to have some way to disable most of the UI (form.controls.first.enabled = false) while leaving it responsive, when a long process (import) runs in the background and reports now and then.
We coded the same behaviour using a background worker, but we didn't like the syntax.
So we came up with that, which is a kind of syntactic symetrical of InUIThread (used all over the place).
Using it feels right in our case, but the implementation sounds weird. Playing with IsBusy and DoEvents is not something I find robust.
Anyway - InUIThread matches a good 95% of our use.
Do you use an InUIThread equivalent ? Or do you rely on BackgroundWorker ?
I'd be interested to have some real-life feedback.
cheers and thanks for your comment.
-- Thibaut
http://codebetter.com/blogs/patricksmacchia/archive/2008/06/10/backgroundworker-closure-and-overridable-task.aspx
This post has 2 feedbacks awaiting moderation...