在catch区等待

Gyö*_*ssy 82 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" ) );
}
Run Code Online (Sandbox Code Playgroud)

基本上我想从URL下载,当它失败时,我想从另一个URL下载异常.两个时间都是异步的.但是代码没有编译,因为

错误CS1985:无法在catch子句的主体中等待

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

编辑:

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

svi*_*ick 99

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


旧答案:您可以使用标志重写该代码以awaitcatch块移动:

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" ) );
Run Code Online (Sandbox Code Playgroud)

  • 如果你甚至需要在不丢失callstack的情况下重新抛出异常,你也可以使用`System.Runtime.ExceptionServices.ExceptionDispatchInfo`静态类.只需在catch块中调用`ExceptionDispatchInfo.Capture(ex)`,并将返回值(捕获的异常)存储在局部变量中.一旦完成了异步代码,就可以使用`capturedException.Throw()`来正确地重新抛出原始异常. (13认同)
  • 谢谢svick,这很明显,什么更好,更多连接到异步? (7认同)
  • 在您的情况下,您还可以使用任务延续.但是`svick`答案中的代码比使用continuation的代码更清晰. (3认同)

Cra*_*aig 24

现在可以在Roslyn的最终用户预览版中等待一个catch块(在catch/finally中的Await下列出),并将包含在C#6中.

列出的例子是

try … catch { await … } finally { await … }
Run Code Online (Sandbox Code Playgroud)

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


Dar*_*agh 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;
Run Code Online (Sandbox Code Playgroud)


Ron*_*Ron 5

尝试一下:

         try
        {
            await AsyncFunction(...);
        }

        catch(Exception ex)
        { 
            Utilities.LogExceptionToFile(ex).Wait();
            //instead of "await Utilities.LogExceptionToFile(ex);"
        }
Run Code Online (Sandbox Code Playgroud)

(见Wait()结尾)