在拦截区等待

我有以下密码:

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 块中的等待调用

33958 次浏览

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

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;

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

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!)

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
}

Give this a try:

         try
{
await AsyncFunction(...);
}


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

(See the Wait() ending)

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();
}

Use C# 6.0. see this Link

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

You can use a lambda expression as follows:

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


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


lambda(ex);
}