On my current project, I was tasked with seeing if I could add some limited auto-complete functionality to the application. The application centers around a designer view where the user drops in and links predefined elements to create a model. In these user defined models, it is often necessary that the properties of one element are calculated from the property values of other elements. I essentially needed a simple intellisense style interface that would allow me to reference a named element and its associated properties. Plus, I needed to know when these textual references went bad because a user deleted or renamed an element. This necessitated building my own prefix tree of possible matches, and keeping that tree up to date as the user modified the data model by adding or removing elements.
I needed to drive my tree generation on the changes to the data model, but the architecture was already doing a lot of work when that happens. The domain required quite a bit of re-rendering and re-calculation of views for the underlying data model. I felt a little nervous also adding some recursive tree generation to the mix. Since our GUI design prevented the user from being able to textually reference an element and change the model at the same time, I felt like this feature was a good candidate for some asynchronous programming.
Pre .NET 4.5 you would have had to spawn a new thread and go through all the trouble of synchronization using locks and semaphores. Luckily Microsoft has given us the new “async” and “await” keywords to simplify the whole process. These new keywords help bring a nice fluid task based programming model into your code base.
Here’s a pretty basic example:
public async void OnDoWorkButtonClick( object sender, RoutedEventArgs e ) { ouptutTextBlock.Text = "Doing Work"; Task
In the UI you see the Text go from “Doing Work” to “Doing More Work”, and then 5 seconds later you see: “Did some async work”. The UI thread is not blocked by the 5 second wait. The GetMeMyStringAsync does begin running immediately, but as soon as it hits the await command it releases the current thread execution and continues on in its own thread. The calling method can go about its own work until it actually needs the results of the asynchronous task. At that point it performs an await, releasing execution back up one level. It completes its own work only when the Task
There’s a few things you should know before playing around with these new features yourself. Your async methods will run synchronously unless you have a call to await another batch of work. Async methods can only return either void or a Task object. You should avoid using void return types on async methods as the calling code will not know when the asynchronous tasks complete. Void async methods should be reserved for the entry point to your asynchronous operation; typically an event handler of some type.
A side effect of this structure is that the Task based model tends to grow through your code base like kudzu. You’ll continually find yourself changing your methods to “async Task
Now if you’re thinking, “Man sounds cool, but my project’s still stuck using .Net 4.0.” Don’t worry. If you are using Visual Studio 2012, you can grab the Microsofy.Bcl.Asyc library though NuGet and use the same features with a slightly altered interface.
We’ve started using async methods in a couple more places in the application and are starting to see improvements in the application’s responsiveness. All for the cost of very minor architectural changes.