Threading and Waiting with Delegates
December 7, 2007
One of the casualties of not having a full computer science education is that I was barely exposed to threading. In my two Java classes we touched upon it, and wrote some basic examples in the second semester, but that could hardly be called extensive use. Thus, a number of years on, it has been a bit of a struggle for me to use threads in a practical manner. Further complicating the matter is that I've wanted to use anonymous methods (aka delegates) and generally want to do some work after all threads have finished executing.
Unfortunately most of the examples I've found deal with one or the other, but in a manner either too simplistic for what I wanted or at cross purposes. For instance, they look pretty static in terms of the number of threads spawned, or don't deal at all with waiting until the threads have finished, or just don't explain themselves very well. But at last I've found the final piece I needed, in Working with Delegates Made Easier with C# 2.0.
I tried creating an array of
WaitHandle objects, but somewhere got something wrong.
I'm sure they're perfectly usable. But then the article above showed me that all I really needed
AutoResetEvent. And in fact, all I needed was one such object. Then to
instantiate my thread I used a
delegate — but did not declare a new
delegate, an early mistake of mine.
This anonymous method runs another function that takes an input paramete, and eventually, when
all threads are finished, releases the
AutoResetEvent. Thankfully the code knows how
to figure out how many threads will be spawned. Finally, run the
WaitOne method on
the instance of
AutoResetEvent in order to pause execution of the rest of the program
until all threads are finished.
/* Trying to process a bunch of files in a directory. */
FileInfo readyFiles = tmpDir.GetFiles();
/* These two variables are the key to signaling that all threads are done. */
AutoResetEvent are = new AutoResetEvent(false);
long numberLeft = readyFiles.Length;
/* Loop through all the files. Could've used a foreach loop, but for is slightly faster */
for (int i = 0; i < readyFiles.Length; i++)
FileInfo f = readyFiles[i];
/* Start a thread with an anonymous method */
/* A private function in the same class that does some action on the input file */
/* I found that the thread would loop infinitely if I tried to let exceptions go, therefore I just catch the exceptions and add them to a list. */
catch (Exception ex)
/* Important to lock this global list, otherwise can get a race condition. */
/* Actually, its a Dictionary
so that I can capture the file name and the exception together. */
/* Important to have this in the finally. Initially it was in the try. I purposefully created an error condition. When I noticed that the threads never stopped, I realized it was because this code had not been hit. */
if (Interlocked.Decrement(ref numberLeft) == 0)
/* Wait for all the threads to finish. */