Jonathan George's Blog

Add Timeouts to your methods with PostSharp

Posted in Technical Stuff by Jonathan on September 15, 2009

Note: This was originally posted on my old blog at the EMC Consulting Blogs site.

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:

  1. public class TimeoutWithoutPostsharp
  2. {
  3.     public object MyMethod(object param)
  4.     {
  5.         var methodDelegate = new Func<object, object>(this.MyMethodInner);
  6.         var result = methodDelegate.BeginInvoke(
  7.             param,
  8.             null,
  9.             null);
  10.         if (!result.AsyncWaitHandle.WaitOne(1000))
  11.         {
  12.             throw new TimeoutException();
  13.         }
  14.         return methodDelegate.EndInvoke(result);
  15.     }
  16.     private object MyMethodInner(object param)
  17.     {
  18.         // Do the work
  19.     }
  20. \

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…

  1. public class TimeoutWithPostSharp
  2. {
  3.     [Timeout(1000)]
  4.     public object MyMethod(object param)
  5.     {
  6.         // Do the work
  7.     }
  8. }

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:

  1. [Serializable]
  2. public class TimeoutAttribute : OnMethodInvocationAspect
  3. {
  4.     /// <summary>
  5.     /// Initializes a new instance of the <see cref=”TimeoutAttribute”/> class.
  6.     /// </summary>
  7.     /// <param name=”timeoutMs”>
  8.     /// The timeout period in ms.
  9.     /// </param>
  10.     public TimeoutAttribute(int timeoutMs)
  11.     {
  12.         this.TimeoutMs = timeoutMs;
  13.     }
  14.     /// <summary>
  15.     /// The timeout period in ms.
  16.     /// </summary>
  17.     public int TimeoutMs { get; set; }
  18.     public override void OnInvocation(MethodInvocationEventArgs eventArgs)
  19.     {
  20.         Action proceedAction = eventArgs.Proceed;
  21.         IAsyncResult result = proceedAction.BeginInvoke(
  22.             null,
  23.             null);
  24.         bool completed = result.AsyncWaitHandle.WaitOne(this.TimeoutMs);
  25.         if (!completed)
  26.         {
  27.             throw new TimeoutException();
  28.         }
  29.         proceedAction.EndInvoke(result);
  30.     }
  31. }

The code for this aspect, along with some unit tests to prove I’m not making all this up, can be downloaded from Codeplex.

@jon_george1

Tagged with: ,

Make methods “fire and forget” with PostSharp

Posted in Technical Stuff by Jonathan on September 10, 2009

Note: This was originally posted on my old blog at the EMC Consulting Blogs site.

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.

  1. class FireAndForgetWithoutPostsharp
  2. {
  3.     public void MySynchronousMethod(string argument)
  4.     {
  5.         ThreadPool.QueueUserWorkItem(
  6.             this.MySynchronousMethodInternal,
  7.             argument);
  8.     }
  9.     private void MySynchronousMethodInternal(object state)
  10.     {
  11.         var argument = state as string;
  12.         // Do the work…
  13.     }
  14. }

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:

  1. public class AsyncAttribute : OnMethodInvocationAspect
  2. {
  3.     public override void OnInvocation(
  4.         MethodInvocationEventArgs eventArgs)
  5.     {
  6.         ThreadPool.QueueUserWorkItem(
  7.             delegate { eventArgs.Proceed(); });
  8.     }
  9. }

Suddenly, you can drop all the boilerplate from the first sample, and you end up with this:

  1. class FireAndForgetWithPostsharp
  2. {
  3.     [Async]
  4.     public void MyMethod(string argument)
  5.     {
  6.         // Do the work
  7.     }
  8. }

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:

  • ThreadPool.QueueUserWorkItem.
  • Calling BeginInvoke on a delegate.
  • Creating a new background thread.

The aspect code now looks like this.

  1. public class AsynchronousAttribute : OnMethodInvocationAspect
  2. {
  3.     public AsynchronousAttribute()
  4.         : this(AsynchronousInvocationOption.ThreadPool)
  5.     {
  6.     }
  7.     public AsynchronousAttribute(AsynchronousInvocationOption invocationOption)
  8.     {
  9.         this.InvocationOption = invocationOption;
  10.     }
  11.     public AsynchronousInvocationOption InvocationOption { get; set; }
  12.     public override void OnInvocation(MethodInvocationEventArgs eventArgs)
  13.     {
  14.         switch (this.InvocationOption)
  15.         {
  16.             case AsynchronousInvocationOption.BackgroundThread:
  17.                 this.InvokeUsingBackgroundThread(eventArgs);
  18.                 break;
  19.             case AsynchronousInvocationOption.Delegate:
  20.                 this.InvokeUsingDelegate(eventArgs);
  21.                 break;
  22.             default:
  23.                 this.InvokeUsingThreadPool(eventArgs);
  24.                 break;
  25.         }
  26.     }
  27.     private void InvokeUsingBackgroundThread(MethodInvocationEventArgs eventArgs)
  28.     {
  29.         var thread = new Thread(eventArgs.Proceed)
  30.         {
  31.             IsBackground = true
  32.         };
  33.         thread.Start();
  34.     }
  35.     private void InvokeUsingDelegate(MethodInvocationEventArgs eventArgs)
  36.     {
  37.         var proceed = new Action(eventArgs.Proceed);
  38.         proceed.BeginInvoke(proceed.EndInvoke, proceed);
  39.     }
  40.     private void InvokeUsingThreadPool(MethodInvocationEventArgs eventArgs)
  41.     {
  42.         ThreadPool.QueueUserWorkItem(delegate { eventArgs.Proceed(); });
  43.     }
  44. \

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.

  1. class FireAndForgetWithPostsharp
  2. {
  3.     [Asynchronous(AsynchronousInvocationOption.Delegate)]
  4.     public void MyMethod(string argument)
  5.     {
  6.         // Do the work
  7.     }
  8. }

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.

 @jon_george1

Tagged with: ,
Follow

Get every new post delivered to your Inbox.