Lets say you have some code that calls the database and processes the results. Here is a simple in-line version.
Since they touch the user interface, Lines 3 thru 7 and 14-21 have to be executed on the GUI thread. Line 13, which actually calls the database, shouldn’t be on the GUI. Normally the way we would fix this is to break up the function into three separate functions using threads and invokes to control where each part gets executed. In earlier versions of C# this was quite tedious and somewhat error prone.
With closures, this becomes downright simple.
Here is how to read the new breakdown of the function.
- Lines 1 thru 11 haven’t changed, they all run synchronously on your GUI thread.
- Lines 12 thru 15 define an anonymous function that will run asynchronously on a background thread.
- Lines 17 thru 25 define an anonymous function that will run asynchronously on the GUI thread, once the background thread is done.
- Line 27 says all the asynchronous functions have been defined and processing can begin.
Now that I’ve shown you how anonymous functions can be used to keep the logical flow of a procedure while the physical flow is broken up into threads, lets talk about closures themselves. We use one closure in this, the resultList variable. It is defined in the synchronously function, set by the background function, and read by the asynchronous GUI function. All three functions get access to this variable, but nothing else does so we don’t have to worry about synchronization.