April 15, 2016 by Christoff Truter C# Threading PostSharp
Before I jump into the subject at hand, I just want to make a little confession.
The very first time I looked at the whole AOP paradigm (many moons ago), I was a victim of authority bias, I solely accepted the opinions of one of our industry leaders, without any investigation and making up my mind for myself.
The thing we need to remember however, is that just like with everything else, AOP can be abused in the wrong hands, which hardly disqualifies it of anything.
I honestly still have my reservations, but I am warming up to it a bit.
But what is AOP all about exactly?
It is all about the separation of the common functionality that span over layers and tiers (e.g. logging, caching, security, validation, benchmarking etc), known as cross cutting concerns, which the various AOP frameworks attempt to achieve with little or no modification to existing source code.
To demonstrate, my poison of choice is C# and a popular AOP solution called PostSharp.
Lets assume for a second that I want to benchmark the performance of some of my code, one way to achieve this would be to instantiate a Stopwatch, like seen below.
using System; using System.Threading; using System.Diagnostics;
using static System.Console; class Program { static void Main(string[] args) { var stopWatch = new Stopwatch(); stopWatch.Start(); Thread.Sleep(5000); stopWatch.Stop(); WriteLine($"void Main at {stopWatch.Elapsed}"); } }
class Program { [Profiler] static void Main(string[] args) { Thread.Sleep(5000); } }
using System; using System.Threading; using System.Diagnostics; using PostSharp.Aspects; using static System.Console; [Serializable] class ProfilerAttribute : OnMethodBoundaryAspect { [NonSerialized] Stopwatch stopWatch; public override void OnEntry(MethodExecutionArgs args) { stopWatch = new Stopwatch(); stopWatch.Start(); } public override void OnExit(MethodExecutionArgs args) { stopWatch.Stop(); Debug.WriteLine($"{args.Method} at {stopWatch.Elapsed}"); } }
In addition to the two overrides in the snippet above, we're also able to override the OnException method (among others), if you would like to handle those exceptions however, you will need to inherit from the OnExceptionAspect class (remember what I said about abuse).
The PostSharp solution also provides us with common patterns (stuff like contracts - precondition checking, logging and threading).
I am not going to go into too much detail in this post, I would however like to elaborate on the threading aspects a little bit.
The threading aspect library aims at creating thread safe code by providing, threading models (freezable, immutable etc), thread dispatching (background, dispatch) and deadlock detection.
To give you a quick overview of the dispatching aspects, observe the following snippet.
using PostSharp.Patterns.Threading; using System; using System.Threading; using System.Windows.Forms; class TestForm : Form { TextBox textBox = new TextBox(); public TestForm() { this.Controls.Add(textBox); this.Load += new EventHandler(TestForm_Load); } [Background] void TestForm_Load(object sender, EventArgs e) { Thread.Sleep(5000); setTextBox(); } [Dispatched] public void setTextBox() { textBox.Text = "dude"; } } class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.Run(new TestForm()); } }