Exception handling in C # asynchronous methods

I know this question has been asked several times, but I am looking at another option a bit.

public async Task<string> SomeAsyncMethod(string url)
{
     // do some URL validation
     if (!valid)
     {
          throw new Exception("some error");
     }
     // do async stuff now
     return await GetFromUrl(url)
}

// now in caller
public async Task<string> SomeOtherAsyncMethod(string input)
{
     var task = SomeAsyncMethod(input); 
    // there is potential chance that a validation fails and  
    //exception is thrown even before entering async parts of the called function

     // do some independent stuff here
    try
    {
        await task;
    } 
    catch(Exception e)
    {
        // log error 
    }

    // is the following code correct way to handle exceptions?
    if (!task.IsFaulted)
    {
        return task.Result; 
    }

    // log error from task.Exception 
    return null;

}

      

In the above code, it may happen that validation fails and an exception is thrown even before the control enters the asynchronous part of the method. Do I need to wrap the first call around the try..catch block as well? My experiment has shown that this is not useful. Instead, the task status is set to Faulted. Therefore, I consider it correct to check the status of the task and return the data accordingly. Can C # comment on this?

+3


source to share


2 answers


As you said, when you have a method async

that throws an exception the method will never throw, instead, the returned tasks will just be thrown by an error. This is true even if the exception is thrown before the first await

. If this is your desired functionality, then you already have it and there is no need to change anything.



+3


source


Do I need to wrap the first call around the try..catch block as well?

You can do this as a protective coding measure. Precondition exceptions in methods async

suffer from the same problems as with enumerator blocks. The async

task exclusion case uses precondition exclusions that do not arise directly. This is how I make pre-exceptions.

However, there is an alternative. It is possible that the implementation will "eagerly" perform precondition checks and only use faulty tasks to represent asynchronous exceptions. I.e:.



public Task<string> SomeMethodAsync(string url)
{
   // do some URL validation
   if (!valid)
   {
     throw new Exception("some error");
   }
   // do async stuff now
   return SomeMethodImplAsync(url);
}

private async Task<string> SomeMethodImplAsync(string url)
{
  return await GetFromUrl(url)
}

      

I don't do it myself, but this approach has its supporters. First of all, Jon Skeet.

With this in mind, unless the documentation explicitly states that precondition exceptions will be placed in the returned task, you should probably include the call SomeMethdAsync

in a block try

.

+3


source







All Articles