remarks generate example c# asynchronous async-await c#-5.0 c#-6.0

c# - generate - Esperar en el bloque catch



params comments c# (9)

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 deseo descargar desde otra URL. Tanto el tiempo asincrónico por supuesto. Sin embargo, el código no se compila, debido a

error CS1985: no puede esperar en el cuerpo de una cláusula de captura

OK, está prohibido por cualquier razón, pero ¿cuál es el patrón de código correcto aquí?

EDITAR:

La buena noticia es que es probable que C # 6.0 permita llamadas en espera tanto en los bloques catch como finally .


El patrón que uso para volver a lanzar la excepción después de esperar en una tarea alternativa:

ExceptionDispatchInfo capturedException = null; try { await SomeWork(); } catch (Exception e) { capturedException = ExceptionDispatchInfo.Capture(e); } if (capturedException != null) { await FallbackWork(); capturedException.Throw(); }


En una instancia similar, no pude esperar en un bloque catch. 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 }


Esperar en un bloque catch ahora es posible a partir de la vista previa del usuario final de Roslyn, como se muestra aquí (enumerados en Aguardar en catch / finally) y se incluirá en C # 6.

El ejemplo mencionado es

try … catch { await … } finally { await … }

Actualización: Se agregó un enlace más nuevo y estará en C # 6


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;


Podrías poner la await después del bloque catch seguido de una label , y poner un goto en el bloque try. (¡No, de verdad! ¡Los de Goto no son tan malos!)


Prueba esto:

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

(Ver el final de Wait() )


Puede usar una expresión lambda de la siguiente manera:

try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); }


Use C # 6.0. ver este enlace

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


Actualización: los soportes de C # 6.0 esperan en la captura

Respuesta anterior : Puede volver a escribir ese código para mover la await del bloque catch usando una bandera:

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