18

I just discovered that, since .NET 4.6, there is a new method FromException on the Task object, and I was wondering what was the best way to throw exceptions in an async method.

Here are two examples:

internal class Program
{
    public static void Main(string[] args)
    {
        MainAsync().Wait();
    }

    private static async Task MainAsync()
    {
        try
        {
            Program p = new Program();
            string x = await p.GetTest1(@"C:\temp1");
        }
        catch (Exception e)
        {
            // Do something here
        }
    }

    // Using the new FromException method
    private Task<string> GetTest1(string filePath)
    {
        if (!Directory.Exists(filePath))
        {
            return Task.FromException<string>(new DirectoryNotFoundException("Invalid directory name."));
        }
        return Task.FromResult(filePath);
    }

    // Using the normal throw keyword
    private Task<string> GetTest2(string filePath)
    {
        if (!Directory.Exists(filePath))
        {
             throw new DirectoryNotFoundException("Invalid directory name.");
        }
        return Task.FromResult(filePath);
    }
}
1
  • 6
    The best way to throw exceptions in an async method is throw. However, neither of your examples are async methods. Commented Jan 19, 2017 at 14:42

1 Answer 1

25

There is a difference in behaviour between GetTest1() and GetTest2.

GetTest1() will not throw the exception when the method is called. Instead it returns a Task<string>. The exception will not be thrown until that task is awaited (we could also have chosen to inspect the task to see if succeeded without ever throwing the exception).

In contrast GetTest2() throws the exception immediately when called without ever returning the Task<string>

I guess which one you use would depend on the desired behaviour. If I had a bunch of GetTest() tasks I wanted to run in parallel and I wanted execution to continue for those tasks that succeeded then I would use Task.FromException which allows me to inspect the results of each Task and act accordingly. In contrast, if any Exception in the list meant I didn't want execution to continue I would likely just throw the Exception.

Sign up to request clarification or add additional context in comments.

5 Comments

That last paragraph doesn't make sense. Task.FromException shouldn't be used in async methods at all.
@StephenCleary removed the offending paragraph - thanks for pointing it out
@Stephen Cleary Why not? For example: private async Task<string> GetTest3(string filePath) { if (!Directory.Exists(filePath)) { return await Task.FromException<string>(new DirectoryNotFoundException("Invalid directory name.")); } ... }
@Bidou: Because await Task.FromException<string>(new DirectoryNotFoundException("Invalid directory name.")); (the return won't compile) is just an overly verbose way of saying throw new DirectoryNotFoundException("Invalid directory name.");
@Stephen Cleary Ok, thank you, this is what I was guessing. By the way, it compiles fine with the return, but this is a detail...

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.