Ожидание в блоке catch
У меня есть следующий код:
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
ОК, это запрещено по какой-либо причине, но каков правильный шаблон кода здесь?
EDIT:
Хорошей новостью является то, что С# 6.0, скорее всего, позволит ждать вызовов как в catch, так и в окончательных блоках.
Ответы
Ответ 1
Обновление: С# 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" ) );
Ответ 2
Ожидание в блоке catch теперь возможно с предварительного просмотра пользователя Roslyn как показано здесь (в списке в списке "Ожидание в catch/finally" ) и будет включен в С# 6.
В приведенном примере указан
try … catch { await … } finally { await … }
Обновление: Добавлена новая ссылка и что она будет в С# 6
Ответ 3
Кажется, что это работает.
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;
Ответ 4
Попробуйте:
try
{
await AsyncFunction(...);
}
catch(Exception ex)
{
Utilities.LogExceptionToFile(ex).Wait();
//instead of "await Utilities.LogExceptionToFile(ex);"
}
(см. окончание Wait()
)
Ответ 5
Образец, который я использую для восстановления исключения после ожидания в резервной задаче:
ExceptionDispatchInfo capturedException = null;
try
{
await SomeWork();
}
catch (Exception e)
{
capturedException = ExceptionDispatchInfo.Capture(e);
}
if (capturedException != null)
{
await FallbackWork();
capturedException.Throw();
}
Ответ 6
Используйте С# 6.0. см. ссылку Ссылка
public async Task SubmitDataToServer()
{
try
{
// Submit Data
}
catch
{
await LogExceptionAsync();
}
finally
{
await CloseConnectionAsync();
}
}
Ответ 7
Вы можете использовать выражение лямбда следующим образом:
try
{
//.....
}
catch (Exception ex)
{
Action<Exception> lambda;
lambda = async (x) =>
{
// await (...);
};
lambda(ex);
}
Ответ 8
Вы можете поместить await
после блока catch, за которым следует label
, и поместите goto
в блок try.
(Нет, действительно! Goto не так уж плохо!)
Ответ 9
В подобном экземпляре я не смог дождаться в блоке 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
}