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 .
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" ) );
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
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;
Essayez ceci:
try
{
await AsyncFunction(...);
}
catch(Exception ex)
{
Utilities.LogExceptionToFile(ex).Wait();
//instead of "await Utilities.LogExceptionToFile(ex);"
}
(Voir la fin de Wait()
)
Utilisez C # 6.0. voir ceci Lien
public async Task SubmitDataToServer()
{
try
{
// Submit Data
}
catch
{
await LogExceptionAsync();
}
finally
{
await CloseConnectionAsync();
}
}
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();
}
Vous pouvez utiliser une expression lambda comme suit:
try
{
//.....
}
catch (Exception ex)
{
Action<Exception> lambda;
lambda = async (x) =>
{
// await (...);
};
lambda(ex);
}
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
}
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!)