在catch block中等待

我有以下代码:

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下载的exception。 这两个时间当然是asynchronous的。 但是代码不能编译,因为

错误CS1985:不能等待catch子句的正文

好的,不论什么原因都是禁止的,但是这里的代码模式是什么?

编辑:

好消息是C#6.0可能允许在catch和finally块中等待调用 。

更新: C#6.0支持在catch中等待


老答案 :您可以重写该代码以使用标志来移动catch块的await

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

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

列出的例子是

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

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

这似乎工作。

  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; 

试试这个:

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

(请参阅Wait()结尾)

你可以像下面这样使用lambdaexpression式:

  try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); } 

在等待回退任务后,我使用该模式重新抛出exception:

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

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

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

你可以在catch块之后加上label ,然后在try块中放一个goto 。 (不,真的!后藤的不是那么糟糕!)

在一个类似的例子中,我无法在一个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 }