The PostSharp Aspect OnSuccess method not being called as expected with Async methods. When I await on Async method, the success is calling before the method returns. My Aspect:
namespace PostSharpConcepts
{
[Serializable]
public class ProfilerAspect : OnMethodBoundaryAspect, IOnStateMachineBoundaryAspect
{
public ProfilerAspect()
{
ApplyToStateMachine = false;
}
public override void OnEntry(MethodExecutionArgs args)
{
args.MethodExecutionTag = Stopwatch.StartNew();
}
public override void OnSuccess(MethodExecutionArgs args)
{
Stopwatch sw = (Stopwatch) args.MethodExecutionTag;
sw.Stop();
string message = string.Format("{0} Executed in {1} seconds, Class : {2}", args.Method.Name, (float)sw.ElapsedMilliseconds / 1000, args.Method.DeclaringType.FullName);
Debug.WriteLine("OnSuccess");
Logger.LogBase(Logger.LogLevel.Debug, message);
}
public override void OnResume(MethodExecutionArgs args)
{
Stopwatch sw = (Stopwatch)args.MethodExecutionTag;
sw.Stop();
string message = string.Format("{0} Executed in {1} seconds, Class : {2}", args.Method.Name, (float)sw.ElapsedMilliseconds / 1000, args.Method.DeclaringType.FullName);
Debug.WriteLine("OnResume");
Logger.LogBase(Logger.LogLevel.Debug, message);
}
}
}
Calling code:
namespace PostSharpConcepts
{
[ProfilerAspect]
class Program
{
static void Main(string[] args)
{
DoSomething();
Console.ReadLine();
}
private async static void DoSomething()
{
Debug.WriteLine("DoSomething - start");
await Task.Run(() => System.Threading.Thread.Sleep(2000));
Debug.WriteLine("DoSomething - end");
}
}
}
Here's the output: DoSomething - start OnSuccess DoSomething - end
Expected output would be as per non Async calls: DoSomething - start DoSomething - end OnSuccess
If you don't specify this.ApplyToStateMachine = true
(you explicitly specify the opposite), PostSharp will apply the aspect just to the method and will not transform the state machine. For IOnStateMachineBoundaryAspect
this should be the default value.
This is backwards compatible behavior, which transforms just the async's method body, not the state machine. Since the first part of the state machine (up to first await) runs synchronously, OnSuccess will be invoked on the first await, when the async method returns a Task. To do what you need, specify this.ApplyToStateMachine = true
.
Note that state machine transformations are currently not included in the Express version and are available only in Professional or higher.