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 veux télécharger à partir d'une URL et en cas d'échec avec une exception, je veux télécharger à partir d'une autre URL. Les deux temps asynchrone bien sûr. Cependant, le code ne se compile pas, à cause 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?
ÉDITER:
La bonne nouvelle est que C # 6.0 autorisera probablement les appels d'attente à la fois dans les blocs catch et finally .
c#
asynchronous
async-await
c#-5.0
c#-6.0
György Balássy
la source
la source
svick
la réponse est plus propre que le code utilisant des continuations.System.Runtime.ExceptionServices.ExceptionDispatchInfo
classe statique. Appelez simplementExceptionDispatchInfo.Capture(ex)
votre bloc catch et stockez la valeur de retour, l'exception capturée, dans une variable locale. Une fois que vous avez terminé avec votre code asynchrone, vous pouvez utilisercapturedException.Throw()
ce qui renverra correctement l'exception d'origine.Attendre dans un bloc catch est désormais possible à partir de l'aperçu utilisateur final de Roslyn comme indiqué ici (répertorié sous Attendre dans catch / finally) et sera inclus dans C # 6.
L'exemple listé est
try … catch { await … } finally { await … }
Mise à jour: Ajout d'un lien plus récent et qu'il sera en C # 6
la source
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;
la source
Essayez ceci:
try { await AsyncFunction(...); } catch(Exception ex) { Utilities.LogExceptionToFile(ex).Wait(); //instead of "await Utilities.LogExceptionToFile(ex);" }
(Voir la
Wait()
fin)la source
Utilisez C # 6.0. voir ce lien
public async Task SubmitDataToServer() { try { // Submit Data } catch { await LogExceptionAsync(); } finally { await CloseConnectionAsync(); } }
la source
Le modèle que j'utilise pour renvoyer l'exception après avoir attendu 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(); }
la source
Vous pouvez utiliser une expression lambda comme suit:
try { //..... } catch (Exception ex) { Action<Exception> lambda; lambda = async (x) => { // await (...); }; lambda(ex); }
la source
async void
, qui ne devrait pas être utilisé, sauf si vous devez le faire.Vous pouvez mettre le
await
après le bloc catch suivi d'unlabel
, et mettre ungoto
dans le bloc try. (Non, vraiment! Les goûts ne sont pas si mauvais!)la source
Dans un cas similaire, je n'ai pas pu attendre dans un bloc catch. Cependant, j'ai pu définir un drapeau et utiliser le drapeau 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 }
la source