web-dev-qa-db-fra.com

Attendre dans le bloc de capture

J'ai le code suivant:

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

Fondamentalement, je souhaite télécharger à partir d'une URL et en cas d'échec avec une exception, je souhaite télécharger à partir d'une autre URL. Les deux temps asynchrones bien sûr. Cependant, le code ne compile pas, en raison de

erreur CS1985: impossible d'attendre dans le corps d'une clause catch

OK, c'est interdit pour une raison quelconque, mais quel est le modèle de code correct ici?

MODIFIER:

La bonne nouvelle est que C # 6.0 permettra probablement d'attendre les appels à la fois dans les captures et enfin dans les blocs .

82
György Balássy

Mise à jour: les supports C # 6.0 attendent en catch


Ancienne réponse : Vous pouvez réécrire ce code pour déplacer le await du bloc catch à l'aide d'un indicateur:

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

L'attente dans un bloc catch est désormais possible à partir de l'aperçu de l'utilisateur final de Roslyn comme indiqué ici (répertorié sous Attendre dans catch/enfin) et sera inclus dans C # 6.

L'exemple répertorié est

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

Mise à jour: Ajout d'un lien plus récent, et qu'il sera en C # 6

24
Craig

Cela semble fonctionner.

        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;
9
Darragh

Essayez ceci:

         try
        {
            await AsyncFunction(...);
        }

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

(Voir la fin de Wait())

5
Ron

Utilisez C # 6.0. voir ceci Lien

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

Le modèle que j'utilise pour renvoyer l'exception après une attente sur une tâche de secours:

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

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}
1
hansmaad

Vous pouvez utiliser une expression lambda comme suit:

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

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

        lambda(ex);
    }
1
Izmoto

Dans un cas similaire, je n'ai pas pu attendre dans un bloc de capture. Cependant, j'ai pu définir un indicateur et l'utiliser dans une instruction if (code ci-dessous)

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

boolean exceptionFlag = false; 

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

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

Vous pouvez mettre le await après le bloc catch suivi d'un label et mettre un goto dans le bloc try. (Non, vraiment! Les Goto ne sont pas si mauvais!)

0
Protector one