У меня такой код:
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, скорее всего, разрешит вызовы await как в блоках catch, так и в блоках finally .
c#
asynchronous
async-await
c#-5.0
c#-6.0
Дьёрдь Балаши
источник
источник
svick
ответе чище, чем код, использующий продолжения.System.Runtime.ExceptionServices.ExceptionDispatchInfo
статический класс. Просто вызовитеExceptionDispatchInfo.Capture(ex)
свой блок catch и сохраните возвращаемое значение, захваченное исключение, в локальной переменной. Как только вы закончите свой асинхронный код, вы можете использовать его,capturedException.Throw()
который будет правильно повторно генерировать исходное исключение.Ожидание в блоке 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()
финал)источник
Используйте C # 6.0. см. эту ссылку
public async Task SubmitDataToServer() { try { // Submit Data } catch { await LogExceptionAsync(); } finally { await CloseConnectionAsync(); } }
источник
Шаблон, который я использую для повторного вызова исключения после ожидания в резервной задаче:
ExceptionDispatchInfo capturedException = null; try { await SomeWork(); } catch (Exception e) { capturedException = ExceptionDispatchInfo.Capture(e); } if (capturedException != null) { await FallbackWork(); capturedException.Throw(); }
источник
Вы можете использовать лямбда-выражение следующим образом:
try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); }
источник
async void
, которую не следует использовать, если вам не нужно.Вы можете поместить
await
после блока catch, за которым следует alabel
, и поместить agoto
в блок try. (Нет, правда! Гото не так уж и плох!)источник
В аналогичном случае я не мог ожидать в блоке 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 }
источник