Every programmer needs to know how and when to use multithreading. Peter Aitken shows you how easy it is to accomplish in .NET.
Every programmer needs to know how and when to use multithreading. Peter Aitken shows you how easy it is to accomplish in .NET.
This article (in particular the example code) contains a serious problem. You *must not* call any methods on ‘Control’-derived classes from any thread other than the one from which they were created.
To do this, you should use Control.(Begin)Invoke() to marshall the call back onto the correct thread. (As an aside, it is almost invariably better to use BeginInvoke(), as Invoke() can cause deadlocks.
In addition, the ‘AutoResetEvent’ business is very odd indeed. That parameter is actually an arbitrary object which you can use to package up any data and pass it to the worker thread. Typically, you would create a class that contains everything you need to do the work off on the worker thread (to avoid sharing state between threads – good practice in multithreaded applications), and upcast it in the worker method. The article implies that it *must* be an autoreset event, which is not true. It also fails to make use of the event anyway…
Furthermore, the example doesn’t address the issues raised in the previous text, of race conditions or deadlocks (e.g. the application exiting before the worker thread has finished).
All in all – take a look around at other examples. This is terrible.
(Ian Griffiths’ article on MSDN is a good place to start)
http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/defau…
I’ll have to second that. The example is crap and does not demonstrate use of basic building blocks.
A basic threading example should at least demonstrate semaphores, mutexes, thread pools, thread pool counters, simulated errors, deadlocks, race conditions, interaction with non-threadsafe code, and memory sharing. Even if the language used takes care of one or more of these, the introduction of the concepts still needs demonstration.
What is being accomplished in the code in the article lends itself much more to asynchronous programming via delegates rather than managing the thread pool via code. Calling BeginInvoke (mentioned by Matthew Adams) on a wrapper delegate is not only more elegant, but frees the programmer from having to worry about managing secondary threads…the CLR manages the threadpool automatically in the background. In this case, polling the IsComplete property of the IAsyncResult object returned by BeginInvoke is the preferred way for a GUI to service worker threads. Callback methods come in handy if the thread that initiates the asynchronous call doesn’t need to process the results. Why try and manage thread pools by hand when it’s already built into the asynchronous classes in the BCL?