在catch区等待

时间:2012-01-15 07:09:16

标签: c# asynchronous async-await c#-5.0 c#-6.0

我有以下代码:

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

基本上我想从URL下载,当它失败并出现异常时我想从另一个URL下载。两个时间都是异步的。但是由于

,代码无法编译
  

错误CS1985:无法等待catch子句的正文

好的,不管出于什么原因这是禁止的,但这里的代码模式是什么?

修改

好消息是C# 6.0 will likely allow await calls both in catch and finally blocks

9 个答案:

答案 0 :(得分:97)

更新: C# 6.0 supports await in catch


旧答案:您可以重写该代码,使用标记从await块移动catch

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

答案 1 :(得分:24)

现在可以在Roslyn as shown here (Listed under Await in catch/finally)的最终用户预览版中等待一个catch块,并将包含在C#6中。

列出的例子是

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

更新:添加了更新的链接,并且它将在C#6中

答案 2 :(得分:9)

这似乎有效。

        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;

答案 3 :(得分:5)

尝试一下:

         try
        {
            await AsyncFunction(...);
        }

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

(参见Wait()结尾)

答案 4 :(得分:2)

使用C#6.0。请参阅此Link

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

答案 5 :(得分:1)

用于在等待回退任务后重新抛出异常的模式:

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

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

答案 6 :(得分:1)

您可以使用lambda表达式,如下所示:

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

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

        lambda(ex);
    }

答案 7 :(得分:0)

您可以将await放在catch块后跟label,然后在try块中放置goto。 (不,真的!后藤不是那么糟糕!)

答案 8 :(得分:0)

在类似的例子中,我无法在catch块中等待。但是,我能够设置一个标志,并在if语句中使用该标志(下面的代码)

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

boolean exceptionFlag = false; 

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

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