Reputation: 1340
I know this question has been asked several times, but, I'm looking slightly at a different variant.
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 so happen that validation fails and exception is thrown even before the control enters async part of the method. Do we need to wrap the first call also around a try..catch block? My experiment showed that this is not useful. Instead, the task status is set to Faulted. So, I believe it is correct to check Task status and return data accordingly. Can C# pros comment on this?
Upvotes: 5
Views: 6411
Reputation: 457322
Do we need to wrap the first call also around a try..catch block?
You may want to do so, as a defensive coding measure. "Precondition" exceptions in async
methods suffer from the same problems as they do with enumerator blocks. In the async
case, the precondition exceptions are used to fault the task, not raised directly. This is how I do precondition exceptions.
However, there is an alternative. It is possible for an implementation to "eagerly" do the precondition checks and only use faulted 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 this myself, but this kind of approach does have its supporters. Most notably, Jon Skeet.
With that in mind, unless the documentation explicitly specifies that precondition exceptions will be placed on the returned task, you probably should include the call to SomeMethdAsync
within a try
block.
Upvotes: 4
Reputation: 203809
As you have already stated, when you have an async
method that throws an exception calling the method will never throw, instead the returned tasks will simply be faulted. This is true even if an exception is thrown before the first await
. If that's your desired functionality, then you already have it, and there is no need to change anything.
Upvotes: 4