Eu tenho o seguinte código:
WebClient wc = new WebClient();
string result;
try
{
result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
}
catch
{
result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
}
Basicamente, quero fazer o download de um URL e, quando falha com uma exceção, quero fazer o download de outro URL. Ambos são assíncronos, é claro. No entanto, o código não compila, por causa de
erro CS1985: não é possível esperar no corpo de uma cláusula catch
OK, é proibido por qualquer motivo, mas qual é o padrão de código correto aqui?
EDITAR:
A boa notícia é que o C # 6.0 provavelmente permitirá chamadas de espera em blocos catch e finally .
c#
asynchronous
async-await
c#-5.0
c#-6.0
György Balássy
fonte
fonte
svick
resposta de é mais limpo do que o código que usa continuações.System.Runtime.ExceptionServices.ExceptionDispatchInfo
classe estática. Simplesmente chameExceptionDispatchInfo.Capture(ex)
seu bloco catch e armazene o valor de retorno, a exceção capturada, em uma variável local. Depois de concluir o código assíncrono, você pode usá-locapturedException.Throw()
para relançar corretamente a exceção original.Aguardar em um bloco de captura agora é possível a partir da Visualização do usuário final de Roslyn, conforme mostrado aqui (listado em Aguardar em captura / finalmente) e será incluído no C # 6.
O exemplo listado é
try … catch { await … } finally { await … }
Update: Adicionado link mais recente, e que estará em C # 6
fonte
Isso parece funcionar.
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;
fonte
Experimente:
try { await AsyncFunction(...); } catch(Exception ex) { Utilities.LogExceptionToFile(ex).Wait(); //instead of "await Utilities.LogExceptionToFile(ex);" }
(Veja o
Wait()
final)fonte
Use C # 6.0. veja este link
public async Task SubmitDataToServer() { try { // Submit Data } catch { await LogExceptionAsync(); } finally { await CloseConnectionAsync(); } }
fonte
O padrão que uso para relançar a exceção após aguardar em uma tarefa de fallback:
ExceptionDispatchInfo capturedException = null; try { await SomeWork(); } catch (Exception e) { capturedException = ExceptionDispatchInfo.Capture(e); } if (capturedException != null) { await FallbackWork(); capturedException.Throw(); }
fonte
Você pode usar uma expressão lambda da seguinte maneira:
try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); }
fonte
async void
, que não deve ser usado, a menos que seja necessário.Você poderia colocar o
await
após o bloco catch seguido por alabel
, e colocar agoto
no bloco try. (Não, sério! Goto's não são tão ruins!)fonte
Em uma instância semelhante, não pude esperar em um bloco de captura. No entanto, consegui definir um sinalizador e usar o sinalizador em uma instrução if (código abaixo)
---------------------------------------...
boolean exceptionFlag = false; try { do your thing } catch { exceptionFlag = true; } if(exceptionFlag == true){ do what you wanted to do in the catch block }
fonte