0

In my winform programme I use Postsharp interceptor class on each control event to avoid try/catch block repetition.

The custom postsharp method:

[Serializable]
public class OnErrorShowMessageBox : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    {
        try
        {               
            args.Proceed();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
            args.ReturnValue = null;
        }
    }
}

Usage this the attributs:

    [OnErrorShowMessageBox]
    private void txtComments_TextChanged(object sender, EventArgs e)
    {
       //blabla
    }

This works like a charm BUT know I would like to use async on the event. So txtComments_textChanged become :

    [OnErrorShowMessageBox]
    private async void txtComments_TextChanged(object sender, EventArgs e)
    {
        await //blabla
    }

And here comes the problem. Try/catch bloc in the interceptor method don't catch anything when is async... How can I do ? thanks

Daniel Kelley
  • 7,579
  • 6
  • 42
  • 50
Julian50
  • 2,462
  • 1
  • 21
  • 30
  • 1
    Are you using version 3.1, which [added support for `async` methods](http://www.postsharp.net/blog/post/New-in-PostSharp-31-Support-for-async-and-iterator-methods)? – Stephen Cleary Mar 25 '15 at 13:47
  • @StephenCleary I use 4.039 version. Maybe your link is the answer, but I don't see how should I modify my code according your link (I'm postsharp beginner) thanks – Julian50 Mar 25 '15 at 14:14
  • @StephenCleary Please stephen, could you help me ? – Julian50 Mar 26 '15 at 07:40
  • I don't think you can do what you're trying to do with an `async void` method. `async void` methods have unusual exception behavior (sending them directly to the current `SynchronizationContext`), which would be extremely difficult to intercept. – Stephen Cleary Mar 26 '15 at 13:48
  • @StephenCleary arf damn it! thanks for your time. – Julian50 Mar 26 '15 at 14:01

1 Answers1

3

First of all, if you need an aspect to handle exceptions, then it's usually better to implement it as OnMethodBoundaryAspect or OnExceptionAspect. In your OnException method you can set args.FlowBehavior to FlowBehavior.Return or FlowBehavior.Continue to prevent the exception from being thrown.

In addition to providing better performance, these aspects can also be applied to async methods by setting the ApplyToStateMachine property to true. There is a caveat though - with state machines it's not possible to change the exception flow behavior. You can still process the exception, but you cannot prevent it from being thrown.

Update. Starting with PostSharp 5.0, it is possible to change the flow behavior of async methods.

[Serializable]
public class MyAspect : OnExceptionAspect
{
    public MyAspect()
    {
        this.ApplyToStateMachine = true;
    }

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine("OnException({0});", args.Exception.Message);
    }
}

If the aspect is not going to be applied to async methods then you can show the message box and ignore the exception, as shown in the following example

Update. Starting with PostSharp 5.0, the following example also works with async methods.

[Serializable]
public class MyAspect : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
        args.ReturnValue = null;
        args.FlowBehavior = FlowBehavior.Return;
    }
}
AlexD
  • 5,011
  • 2
  • 23
  • 34
  • thanks for your answer. I'm a really aspect beginner. Is it possible to get the full code with my sample 'OnErrorShowMessageBox' in the question please ? I don't see how to use your code in the question thanks. – Julian50 Mar 27 '15 at 08:55
  • 2
    The second example shows the aspect that is the equivalent to your original aspect. Unfortunately, changing the flow behavior will not work if you apply the aspect to async methods. What you can do with async methods is to at least log the exception, as shown in the first example. – AlexD Mar 27 '15 at 11:44