Aspettare nel blocco catch

Ho il codice seguente:

WebClient wc = new WebClient(); string result; try { result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) ); } catch { result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) ); } 

In pratica, voglio scaricare da un URL e quando fallisce con un’eccezione, voglio scaricarlo da un altro URL. Naturalmente asincrono entrambe le ore. Tuttavia il codice non viene compilato, a causa di

errore CS1985: Imansible attendere nel corpo di una clausola catch

OK, è vietato per qualsiasi motivo, ma qual è il modello di codice corretto qui?

MODIFICARE:

La buona notizia è che C # 6.0 probabilmente consentirà di attendere le chiamate sia in catch che ai blocchi .

Aggiornamento: i supporti C # 6.0 attendono in cattura


Vecchia risposta : puoi riscrivere quel codice per spostare l’ await dal blocco catch usando una bandiera:

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

Awaiting in a catch block è ora ansible dall’anteprima utente finale di Roslyn come mostrato qui (elencato in Attesa in catch / finally) e sarà incluso in C # 6.

L’esempio elencato è

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

Aggiornamento: Aggiunto il collegamento più recente e che sarà in C # 6

Questo sembra funzionare.

  WebClient wc = new WebClient(); string result; Task 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; 

Fare un tentativo:

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

(Vedi il finale Wait() )

Usa C # 6.0. guarda questo link

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

Lo schema che utilizzo per rilanciare l’eccezione dopo l’attesa in un’attività di fallback:

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

Puoi usare un’espressione lambda come segue:

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

Potresti mettere l’ await dopo il blocco catch seguito da label e inserire un goto nel blocco try. (No, davvero! Goto’s non è poi così male!)

In un caso simile, non ero in grado di aspettare in un blocco di cattura. Tuttavia, sono stato in grado di impostare un flag e utilizzare il flag in una dichiarazione if (codice sotto)

—————————————…

 boolean exceptionFlag = false; try { do your thing } catch { exceptionFlag = true; } if(exceptionFlag == true){ do what you wanted to do in the catch block }