Await in catch block

32,945

Solution 1

Update: C# 6.0 supports await in catch


Old Answer: You can rewrite that code to move the await from the catch block using a flag:

WebClient wc = new WebClient();
string result = null;
bool downloadSucceeded;
try
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
  downloadSucceeded = true;
}
catch
{
  downloadSucceeded = false;
}

if (!downloadSucceeded)
  result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );

Solution 2

Awaiting in a catch block is now possible as of the End User Preview of Roslyn as shown here (Listed under Await in catch/finally) and will be included in C# 6.

The example listed is

try … catch { await … } finally { await … }

Update: Added newer link, and that it will be in C# 6

Solution 3

This seems to work.

        WebClient wc = new WebClient();
        string result;
        Task<string> downloadTask = wc.DownloadStringTaskAsync(new Uri("http://badurl"));
        downloadTask = downloadTask.ContinueWith(
            t => {
                return wc.DownloadStringTaskAsync(new Uri("http://google.com/")).Result;
            }, TaskContinuationOptions.OnlyOnFaulted);
        result = await downloadTask;

Solution 4

Give this a try:

         try
        {
            await AsyncFunction(...);
        }

        catch(Exception ex)
        { 
            Utilities.LogExceptionToFile(ex).Wait();
            //instead of "await Utilities.LogExceptionToFile(ex);"
        }

(See the Wait() ending)

Solution 5

Use C# 6.0. see this Link

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}
Share:
32,945

Related videos on Youtube

György Balássy
Author by

György Balássy

György Balássy is working as a Principal Engineer on LogMeIn’s next generation Internet of Things (IoT) cloud platform. Before joining LogMeIn, he has been teaching web technologies and techniques on the Budapest University of Technology and Economics. He is a founding member of the local MSDN Competence Centre having important role in evangelizing the .NET platform as a speaker, book author and consultant. György provided leadership in the foundation of the Hungarian .NET community as a key evangelist on Microsoft events, technical forums and as the head of the Portal Technology Group in the MSDNCC. He is a regular speaker on community and industrial events presenting in-depth technical sessions on .NET, ASP.NET, Office development and ethical hacking, with which he won the Best Speaker and the Most Valuable Professional Awards in SharePoint, ASP.NET and IIS in every years since 2004, and was selected to be the member of the ASPInsiders group. Between 2005 and 2015 György has been the Microsoft Regional Director in Hungary.

Updated on July 08, 2022

Comments

  • György Balássy
    György Balássy almost 2 years

    I have the following code:

    WebClient wc = new WebClient();
    string result;
    try
    {
      result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
    }
    catch
    {
      result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
    }
    

    Basically I want to download from a URL and when it fails with an exception I want to download from another URL. Both time async of course. However the code does not compile, because of

    error CS1985: Cannot await in the body of a catch clause

    OK, it's forbidden for whatever reason but what's the correct code pattern here?

    EDIT:

    The good news is that C# 6.0 will likely allow await calls both in catch and finally blocks.

  • György Balássy
    György Balássy over 12 years
    Thanks svick, that's quite obvious, anything better, more connected to async?
  • svick
    svick over 12 years
    I don't think anything like that exists.
  • Stephen Cleary
    Stephen Cleary over 12 years
    In your case, you could also use task continuations. But the code in svick's answer is cleaner than code using continuations.
  • Etienne Maheu
    Etienne Maheu over 9 years
    If you even need to rethrow the exception without loosing the callstack, you can also use the System.Runtime.ExceptionServices.ExceptionDispatchInfo static class. Simply call ExceptionDispatchInfo.Capture(ex) in your catch block and store the return value, the captured exception, in a local variable. Once you're done with your async code, you can use capturedException.Throw() which will properly rethrow the original exception.
  • Zia Ur Rahman
    Zia Ur Rahman almost 7 years
    awesome technique
  • Tim Lovell-Smith
    Tim Lovell-Smith over 6 years
    And what VS version is that in? Answer: C# 6 is in the box in Visual Studio 2015 (and its preview).
  • svick
    svick over 6 years
    This makes the lambda async void, which should not be used, unless you have to.