2012-01-15 22 views
73

Ho il seguente codice:aspettano in blocco catch

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

Fondamentalmente voglio scaricare da un URL e quando non riesce con un'eccezione Vorrei scaricare da un altro URL. Naturalmente asincrono entrambe le ore. Tuttavia il codice non viene compilato, a causa di

errore CS1985: Impossibile attendere nel corpo di una clausola catch

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

EDIT:

La buona notizia è che C# 6.0 will likely allow await calls both in catch and finally blocks.

risposta

87

Aggiornamento:C# 6.0 supports await in catch


Vecchio Risposta: È possibile riscrivere il codice per spostare il await dal blocco catch con 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")); 
+7

Grazie svick, questo è abbastanza ovvio, niente di meglio, più legato async? –

+0

Non penso che esista qualcosa del genere. – svick

+3

Nel tuo caso, potresti anche utilizzare la continuazione delle attività. Ma il codice nella risposta di 'svick' è più pulito del codice usando le continuazioni. –

9

Questo sembra funzionare.

 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; 
24

attesa in un blocco catch è ora possibile, come del utente finale Anteprima di Roslyn as shown here (Listed under Await in catch/finally) e saranno inclusi in C# 6.

L'esempio elencato è

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

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

0

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

0

In un caso simile, non ero in grado di attendere in un blocco catch. Tuttavia, sono stato in grado di impostare un flag e utilizzare il flag in un'istruzione if (codice di seguito)

------------------------ ---------------...

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
} 
4

dare una prova:

  try 
     { 
      await AsyncFunction(...); 
     } 

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

(Vedere la Wait() finale)

1

il modello che ho utilizzare 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(); 
} 
2

Utilizzare C# 6.0.vedere questo Link

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

È possibile utilizzare un'espressione lambda come segue:

try 
    { 
     //..... 
    } 
    catch (Exception ex) 
    { 
     Action<Exception> lambda; 

     lambda = async (x) => 
     { 
      // await (...); 
     }; 

     lambda(ex); 
    } 
+0

Ciò rende il lambda 'vuoto asincrono', che non dovrebbe essere usato, a meno che non sia necessario. – svick

Problemi correlati