4

Supposed you have 2 async method define as bellow:

public async Task<TResult> SomeMethod1()
{
    throw  new Exception();
}

public async Task<TResult> SomeMethod2()
{
    await Task.Delay(50);
    throw new Exception();
}

Now if you await on those 2 methods the behavior will be pretty much the same. But if you are getting the task the behavior is different.

If I want to cache the result of such a computation but only when the task run to completion. I have to take care of the 2 situation:

First Situation:

public Task<TResult> CachingThis1(Func<Task<TResult>> doSomthing1)
{
    try
    {
       var futur = doSomthing1()
       futur.ContinueWith(
               t =>
               {
                  // ... Add To my cache
               },
               TaskContinuationOptions.NotOnFaulted);
    }
    catch  ()
    {
        // ... Remove from the pending cache
        throw;
    }
}

Second Situation

public Task<TResult> CachingThis2(Func<Task<TResult>> doSomthing)
{
    var futur = SomeMethod2();
    futur.ContinueWith(
       t =>
       {
           // ... Add To my cache
       },
       TaskContinuationOptions.NotOnFaulted);
    futur.ContinueWith(
       t =>
       {
          // ... Remove from the pending cache
       },
       TaskContinuationOptions.OnlyOnFaulted);
}

Now I pass to my caching system the method that will execute the computation to cache.

cachingSystem.CachingThis1(SomeMethod1);
cachingSystem.CachingThis2(SomeMethod2);

Clearly I need to duplicate code in the "ConinueWith on faulted" and the catch block. Do you know if there is a way to make the exception behave the same whether it is before or after an await?

2
  • 2
    If I'm not wrong, your catch block will never execute as the exception propagation for the async methods are different. Commented Nov 24, 2014 at 14:04
  • You must be true but my example miss something crucial that I have omit. See my edit Commented Nov 24, 2014 at 14:16

2 Answers 2

3

There's no difference in the exception handling required for both SomeMethod1 and SomeMethod2. They run exactly the same way and the exception would be stored in the returned task.

This can easily be seen in this example;

static void Main(string[] args)
{
    try
    {
        var task = SomeMethod1();
    }
    catch
    {
        // Unreachable code
    }
}

public static async Task SomeMethod1()
{
    throw new Exception();
}

No exception would be handled in this case since the returned task is not awaited.

There is however a distinction between a simple Task-returning method and an async method:

public static Task TaskReturning()
{
    throw new Exception();
    return Task.Delay(1000);
}

public static async Task Async()
{
    throw new Exception();
    await Task.Delay(1000);
}

You can avoid code duplication by simply having an async wrapper method that both invokes the method and awaits the returned task inside a single try-catch block:

public static async Task HandleAsync()
{
    try
    {
        await TaskReturning();
        // Add to cache.
    }
    catch
    {
        // handle exception from both the synchronous and asynchronous parts.
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

In addition to what I3arnon said in his answer, in case you ContinueWith on async method without the TaskContinuationOptions you specify, exception captured by the Task parameter you receive in the continuation handler can be handled in the following way:

SomeMethod1().ContinueWith(ProcessResult);
SomeMethod2().ContinueWith(ProcessResult);

With ProcessResult handler which looks like:

private void ProcessResult<TResult>(Task<TResult> task)
{
    if (task.IsFaulted)
    {
        //remove from cahe
    }
    else if (task.IsCompleted)
    {
        //add to cache
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.