Welcome to EMC Consulting Blogs Sign in | Join | Help

Jonathan George's Blog

Make methods “fire and forget” with PostSharp

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

Published Thursday, September 10, 2009 11:32 PM by jonathan.george
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Jonathan George's Blog : Add Timeouts to your methods with PostSharp said:

September 15, 2009 10:53 AM
 

Serge Desmedt said:

I've just started looking at PostSharp recently and it looks great. However, I would like you opinion on the following:

As in your example you apply the attribute to the method, which makes the method asynchronous.

However, I've always wondered with AOP and attributes: should I apply the aspect to the method, or to the place where the method is called. Or rephrased: is calling asynchronous a property of the method or of the methodcall? Using attributes makes it a property of the method.

Same goes for Singletons: should a class be a Singleton, or should the useage (thus the object) be a singleton?

The answer probably is, as always: "depends on the specific use-case", but I just like to hear your opinion.

September 16, 2009 7:03 AM
 

jonathan.george said:

Serge,

Most of the definitions of AOP state that the goal is to allow separation of cross cutting concerns (caching, logging, security, etc) from the main codebase. In those scenarios, the aspect would always be applied to the method rather than the call.

In the case of the async and timeout attributes I've written about, they are just about removing repetitive code from your classes. The short answer is that you should apply them wherever you would have put the code if they didn't exist. So if you would have added the async code at the point of calling, then that's where you should apply the aspect.

With the singleton example, I think it's a bit more straightforward - the designer of the class should specify how it can be used. Using a class that isn't intended to be a singleton as one can have nasty consequences, most notably if that class is not thread safe.

Does that make sense? Have you got any examples that have raised this question in your codebase?

September 16, 2009 9:38 AM
 

Serge Desmedt said:

Jonathan,

Thanks for the answer.

I don't have any specific case in mind, and currently (and probably not in the near future) we are not using any AOP.

It was more a theoretical question.

But about the singleton, I was once writing a class that provided some sort of caching functionality. However, it could be that an application requires multiple caches and another requires a single cache. So, the singleton property holds in the one case, but doesn't in the other. I would then like to be able to apply the singleton in my application and not on the caching class itself.

Serge

September 18, 2009 6:40 AM

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server (Personal Edition), by Telligent Systems