In my previous post, “Make methods fire and forget with PostSharp”, I showed how a PostSharp aspect could be used to stop non-critical methods from blocking execution. Staying on a similar theme, in this post I will show how you can use the AOP framework to add timeouts to methods.
In one of my current projects, we’re using Microsoft Velocity CTP3. Whilst this is proving to be pretty good, it has an annoying tendancy to take the entire site down with it if it blows up. We therefore added some code to allow the site to keep running if the cache stops working so that the problem could be rectified without causing more than a slowdown. This code worked perfectly, but I hit the minor snag that Velocity operations like DataCacheFactory.GetCache appear to have something like a 10 second timeout. Our app will typically make tens of calls to the cache to generate a single page so whilst I stopped the site crashing, it was still unusable.
I couldn’t find a way to lower the timeout in Velocity, so I had to implement it in my own methods. The standard code for adding a 1 second timeout in a method would look something like this:
We create a delegate to the method proper, which we can then invoke using BeginInvoke() on the delegate. This returns an IAsyncResult, from which we can use the AsyncWaitHandle to wait for the method to complete. The WaitOne method allows us to specify the timeout interval we want, and returns true if the method completes within that period. If it doesn’t, we raise a TimeoutException, otherwise we call EndInvoke() on the delegate and return the correct value.
If you read my previous post you’ll know what to expect with PostSharp in play…
Again, all the plumbing is eliminated and you end up with clean code in which it’s obvious what’s going on. As with the Asynchronous attribute, this is implemented by inheriting the PostSharp.Laos.OnMethodInvocationAspect base class, which replaces the original method with a generated one that calls into your attribute. The code is straightforward, following the pattern shown in the first code snippet:
The code for this aspect, along with some unit tests to prove I’m not making all this up, can be downloaded from Codeplex.
Since I first encountered it a year or so ago, I’ve been dabbling with PostSharp, an Aspect Oriented Programming framework for .NET. In a recent blog post, Howard mentioned it and showed an aspect that can be used to remove a whole load of the boilerplate code required to implement the INotifyPropertyChanged interface. Whilst he was good enough to name check me for the creation of that code, I’ll ‘fess up now and admit that I didn’t write it myself – I picked it up from Pete Weissbrod’s blog and put it into a form where I could use it to hijack a conversation taking place on one of our internal mailing lists. If you want to get hold of that code and have a look, then you can get hold of the aspect plus tests from Codeplex.
We’ve started to build up a library of aspects to cover various things common to a lot of projects, for example caching and performance monitoring. I’m planning on writing about these over the coming weeks/months, but I thought it would be sensible to start with the most straightforward.
I recently came across a situation where I wanted to make a method “fire and forget” – i.e. I didn’t need a return value, and I didn’t want it to block execution of subsequent code. This is the kind of code you’d probably write to achieve that.
This code isn’t great, because the fact that we’re making the method non-blocking makes it more complex and obscures its real purpose. Enter PostSharp and this sample code from the homepage:
Suddenly, you can drop all the boilerplate from the first sample, and you end up with this:
Clearly this is much nicer – there’s nothing getting in the way of understanding what the code is supposed to be doing, and you can instantly see that the method will actually be non-blocking because of the attribute.
The async attribute is implemented using the OnMethodInvocationAspect base class from the PostSharp.Laos namespace. When the PostSharp weaver runs, it renames your original method and replaces it with a new method. This calls the OnInvocation method of your the aspect, passing a MethodInvocationEventArgs object which contains (amongst other things) the arguments passed to your method, the return value, and a Delegate pointing back to your renamed original method. It also has the Proceed() method which is used to invoke the original method.
Shortly after I implemented this in my web application, I noticed some odd behaviour when the site was under heavy load. Some digging turned up a school of thought which says that using ThreadPool.QueueUserWorkItem in a high traffic web app (which coincidentally is what I’m working on) is not a great idea – see Mads Kristensen’s article or this post on StackOverflow. I decided to switch to an alternative method, and modified the aspect to allow it to use one of three asynchronous invocation methods:
- Calling BeginInvoke on a delegate.
- Creating a new background thread.
The aspect code now looks like this.
As you can see, I have a new property, set via a constructor argument, that allows the user to specify the way in which their method is made asynchronous.
Disclaimer: Before using this in anger, you need to make sure you’re aware of the implications of invoking methods asynchronously. A couple of gotchas you may spot are:
- Any exceptions which are thrown by the method are swallowed, as there’s nothing to handle them. Therefore when making a method fire-and-forget, ensure you add a try-catch block in to do any necessary logging/clean up and prevent the exception taking your app down.
- Threads created as background threads die with the app. So if you fire off an operation on a background thread in your console app, and that app then exits, the operation may not complete. Ultimately, there’s no way to guarantee 100% that your method will run when using this approach – so only use it if you can accept this risk. If you need guaranteed execution then there are various ways of achieving it, ranging from the simple (use of AutoResetEvent) to the full-on message queue based solution.
Whilst I find Postsharp aspects to be very useful, it’s worth making the point that (like a lot of things in software development) the Pareto principle applies. In all likelihood, a relatively basic aspect implementation will cover the majority of your requirements, and the rest can be covered by custom code as needed, so there’s no need to try and make the aspect cover every eventuality
You can download the code, with unit tests to prove that it really is doing what it should, from Codeplex.
Aspects I’m currently planning to cover in future posts are (listed in increasing order of complexity):
- TimeOut – Another simple one, this allows a timeout period to be specified for any method and causes a TimeoutException to be thrown if the method execution time exceeds that period.
- Performance monitoring – Aspects to time and count method executions and write to Windows performance counters.
- Caching – Caches the results of a method call. There’s a basic example of this on the Postsharp site, but it doesn’t cover how to generate appropriate cache keys.
- Logging – Adds entry and exit logging to methods. I’m hoping to persuade James to break off from his Agile/MVC/BDD blogging and write this one up, since he wrote the one in our core library.
If you find this interesting and/or useful, please leave me a comment or rate this article.