György Balássy
György Balássy

Reputation: 2988

Await in catch block

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.

Upvotes: 88

Views: 36340

Answers (9)

user5447154
user5447154

Reputation:

Use C# 6.0. see this Link

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}

Upvotes: 4

svick
svick

Reputation: 244767

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" ) );

Upvotes: 108

Izmoto
Izmoto

Reputation: 1959

You can use a lambda expression as follows:

  try
    {
        //.....
    }
    catch (Exception ex)
    {
        Action<Exception> lambda;

        lambda = async (x) =>
        {
            // await (...);
        };

        lambda(ex);
    }

Upvotes: 1

hansmaad
hansmaad

Reputation: 18905

The pattern I use to rethrow the exception after await on a fallback task:

ExceptionDispatchInfo capturedException = null;
try
{
  await SomeWork();
}
catch (Exception e)
{
  capturedException = ExceptionDispatchInfo.Capture(e);
}

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}

Upvotes: 1

Craig
Craig

Reputation: 7671

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

Upvotes: 23

Ron
Ron

Reputation: 1894

Give this a try:

         try
        {
            await AsyncFunction(...);
        }

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

(See the Wait() ending)

Upvotes: 9

Amanda Berenice
Amanda Berenice

Reputation: 1

In a similar instance, I was unable to await in a catch block. However, I was able to set a flag, and use the flag in an if statement (Code below)

---------------------------------------...

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}

Upvotes: 0

Protector one
Protector one

Reputation: 7261

You could put the await after the catch block followed by a label, and put a goto in the try block. (No, really! Goto's aren't that bad!)

Upvotes: 1

Darragh
Darragh

Reputation: 2656

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;

Upvotes: 9

Related Questions