Tengo el siguiente 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" ) );
}
Básicamente, quiero descargar desde una URL y cuando falla con una excepción, quiero descargar desde otra URL. Ambos tiempos asincrónicos, por supuesto. Sin embargo, el código no se compila, debido a
error CS1985: No se puede esperar en el cuerpo de una cláusula de captura
Está bien, está prohibido por cualquier motivo, pero ¿cuál es el patrón de código correcto aquí?
EDITAR:
La buena noticia es que C # 6.0 probablemente permitirá llamadas en espera tanto en los bloques de captura como de finalmente .
c#
asynchronous
async-await
c#-5.0
c#-6.0
György Balássy
fuente
fuente
svick
respuesta del código in es más limpia que el código que usa continuaciones.System.Runtime.ExceptionServices.ExceptionDispatchInfo
clase estática. Simplemente llameExceptionDispatchInfo.Capture(ex)
a su bloque de captura y almacene el valor de retorno, la excepción capturada, en una variable local. Una vez que haya terminado con su código asincrónico, puede usar elcapturedException.Throw()
que volverá a generar correctamente la excepción original.Esperar en un bloque de captura ahora es posible a partir de la Vista previa del usuario final de Roslyn como se muestra aquí (Listado en Espera en captura / finalmente) y se incluirá en C # 6.
El ejemplo enumerado es
try … catch { await … } finally { await … }
Actualización: se agregó un enlace más nuevo y estará en C # 6
fuente
Esto 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;
fuente
Prueba esto:
try { await AsyncFunction(...); } catch(Exception ex) { Utilities.LogExceptionToFile(ex).Wait(); //instead of "await Utilities.LogExceptionToFile(ex);" }
(Ver el
Wait()
final)fuente
Utilice C # 6.0. ver este enlace
public async Task SubmitDataToServer() { try { // Submit Data } catch { await LogExceptionAsync(); } finally { await CloseConnectionAsync(); } }
fuente
El patrón que utilizo para volver a lanzar la excepción después de esperar en una tarea de respaldo:
ExceptionDispatchInfo capturedException = null; try { await SomeWork(); } catch (Exception e) { capturedException = ExceptionDispatchInfo.Capture(e); } if (capturedException != null) { await FallbackWork(); capturedException.Throw(); }
fuente
Puede usar una expresión lambda de la siguiente manera:
try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); }
fuente
async void
, que no debe usarse, a menos que sea necesario.Podrías poner el
await
después del bloque catch seguido de alabel
, y poner agoto
en el bloque try. (¡No, de verdad! ¡Los Goto no son tan malos!)fuente
En un caso similar, no pude esperar en un bloque de captura. Sin embargo, pude establecer una bandera y usar la bandera en una declaración if (código a continuación)
---------------------------------------...
boolean exceptionFlag = false; try { do your thing } catch { exceptionFlag = true; } if(exceptionFlag == true){ do what you wanted to do in the catch block }
fuente