Anonymous methods are a great new feature in .Net 2. Another great new feature is the ParameterizedThreadStart delegate. Since the ParameterizedThreadStart delegate is just a delegate, these two concepts can be combined to effectively create an asynchronous anonymous method – an anonymous thread, if you will. You can spin off a chunk of code to run asynchronously without having to put it into a separate function. Check out the following code:
private void AddAsync(int a, int b)
{
//Define the code we want to run asynchronously.
// Note that an anonymous delegate works just
// as well as a ParameterizedThreadStart
Thread t = new Thread(delegate(object paramArray)
{
//get the data we passed into the thread
object[] param = paramArray as object[];
//do your long-running process here (this part runs asynchronously)
Thread.Sleep(1000);
int result = (int)param[0] + (int)param[1];
//when we're done with our asynchronous processing, hit the callback function
this.Invoke(new AdditionDoneDelegate(AdditionDone), new object[] { result });
});
//start running the asynchronous code
t.Start(new object[] { a, b });
}
private delegate void AdditionDoneDelegate(int result);
private void AdditionDone(int result)
{
//this gets called when your asynchronous processing is done
MessageBox.Show(result.ToString());
}
Another cool application for this is to create a partially asynchronous function. You can enclose a long running data access operation, for example, within an anonymous thread and use a non-blocking wait (a mutex) to keep the rest of the function from running until the operation is complete. That’s right, you can make just part of your function run asynchronously:
private void AddPartiallyAsync(int a, int b)
{
int result = 0;
Mutex mutex = new Mutex();
Thread t = new Thread(delegate()
{
//do your long-running process here (this part runs asynchronously)
Thread.Sleep(1000);
result = a + b;
//when we're done with our asynchronous processing, release the mutex
mutex.ReleaseMutex();
});
//start running the asynchronous code
t.Start(new object[] { a, b });
//non-blocking-wait here until the thread is done
mutex.WaitOne();
//continue the function here...
MessageBox.Show(result.ToString());
}
Notice that the code inside the anonymous asynchronous method can access variables defined in the surrounding function. I fully expected there to be scoping that would prevent this. But, amazingly, it works. However, I wouldn’t be surprised if this behavior was eliminated in a later version of the framework. Another surprising part of all this is how well the debugger handles it. Simply amazing!