85

我有以下代码:

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 可能会在 catch 和 finally 块中允许 await 调用

4

9 回答 9

106

更新: C# 6.0 支持 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" ) );
于 2012-01-15T12:24:33.907 回答
23

从 Roslyn 的最终用户预览版开始,现在可以在 catch 块中等待,如此处所示(在 catch/finally 中的等待下列出),并将包含在 C# 6 中。

列出的示例是

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

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

于 2014-04-16T18:35:47.373 回答
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;
于 2012-10-27T15:55:41.143 回答
7

试试这个:

         try
        {
            await AsyncFunction(...);
        }

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

(见Wait()结局)

于 2015-03-04T01:21:33.553 回答
4

使用 C# 6.0。看到这个链接

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}
于 2015-10-16T00:48:17.997 回答
1

您可以await在 catch 块之后label放置 a ,然后将 agoto放在 try 块中。(不,真的!Goto 还不错!)

于 2014-11-10T10:56:26.763 回答
1

在等待回退任务后,我用来重新引发异常的模式:

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

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}
于 2015-07-02T08:40:54.883 回答
1

您可以按如下方式使用 lambda 表达式:

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

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

        lambda(ex);
    }
于 2015-11-08T07:37:19.877 回答
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 
}
于 2015-02-08T10:05:05.630 回答