Ce n'est pas un doublon de "Comment appeler en toute sécurité une méthode async en C # sans attendre" .
Comment supprimer gentiment l'avertissement suivant?
avertissement CS4014: Cet appel n'étant pas attendu, l'exécution de la méthode actuelle se poursuit avant la fin de l'appel. Envisagez d'appliquer l'opérateur 'await' au résultat de l'appel.
Un exemple simple:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Ce que j'ai essayé et je n'ai pas aimé:
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Mis à jour , puisque la réponse acceptée d'origine a été modifiée, j'ai changé la réponse acceptée par celle utilisant les rejets C # 7.0 , car je ne pense pas que ce ContinueWith
soit approprié ici. Chaque fois que j'ai besoin de consigner des exceptions pour des opérations d'incendie et d'oubli, j'utilise une approche plus élaborée proposée par Stephen Cleary ici .
la source
#pragma
n'est pas gentil?async void
méthode d'assistance.Réponses:
Avec C # 7, vous pouvez désormais utiliser les rejets :
la source
_ = ...
dans mon cerveau.#pragma warning disable CSxxxx
semble plus moche que le rejet;)Vous pouvez créer une méthode d'extension qui empêchera l'avertissement. La méthode d'extension peut être vide ou vous pouvez y ajouter la gestion des exceptions
.ContinueWith()
.Cependant, ASP.NET compte le nombre de tâches en cours d'exécution, il ne fonctionnera donc pas avec l'
Forget()
extension simple comme indiqué ci-dessus et peut échouer à la place avec l'exception:Avec .NET 4.5.2, il peut être résolu en utilisant
HostingEnvironment.QueueBackgroundWorkItem
:la source
TplExtensions.Forget
. Il y a beaucoup plus de bonté sousMicrosoft.VisualStudio.Threading
. Je souhaite qu'il soit rendu disponible pour une utilisation en dehors du SDK Visual Studio.Vous pouvez décorer la méthode avec l'attribut suivant:
En gros, vous dites au compilateur que vous savez ce que vous faites et qu'il n'a pas besoin de s'inquiéter d'une éventuelle erreur.
La partie importante de ce code est le deuxième paramètre. La partie "CS4014:" supprime l'avertissement. Vous pouvez écrire tout ce que vous voulez sur le reste.
la source
[SuppressMessage("Compiler", "CS4014")]
supprime le message dans la fenêtre Liste des erreurs, mais la fenêtre Sortie affiche toujours une ligne d'avertissementMes deux façons de gérer cela.
Enregistrez-le dans une variable d'élimination (C # 7)
Exemple
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);
Depuis l'introduction des rejets dans C # 7, je considère maintenant que c'est mieux que de supprimer l'avertissement. Parce qu'il supprime non seulement l'avertissement, mais rend également clair l'intention d'incendier et d'oublier.
De plus, le compilateur pourra l'optimiser en mode version.
Supprimez-le simplement
est une solution assez sympa pour "tirer et oublier".
La raison pour laquelle cet avertissement existe est que dans de nombreux cas, vous n'avez pas l'intention d'utiliser une méthode qui renvoie une tâche sans l'attendre. Il est logique de supprimer l'avertissement lorsque vous avez l'intention de tirer et d'oublier.
Si vous ne parvenez pas à vous souvenir de l'orthographe
#pragma warning disable 4014
, laissez simplement Visual Studio l'ajouter pour vous. Appuyez sur Ctrl +. pour ouvrir "Actions rapides", puis "Supprimer CS2014"En tout
C'est stupide de créer une méthode qui prend quelques ticks de plus à exécuter, juste dans le but de supprimer un avertissement.
la source
[MethodImpl(MethodImplOptions.AggressiveInlining)] void Forget(this Task @this) { } /* ... */ obj.WorkAsync().Forget();
AggressiveInlining
le compilateur, je l'ignore pour une raison quelconque#pragma warning disable 4014
, puis de restaurer l'avertissement par la suite avec#pragma warning restore 4014
. Cela fonctionne toujours sans le code d'erreur, mais si vous n'ajoutez pas le numéro d'erreur, tous les messages seront supprimés.Un moyen simple d'arrêter l'avertissement est d'attribuer simplement la tâche lors de son appel:
Et donc dans votre message d'origine, vous feriez:
la source
task
ressemble à une variable locale oubliée. Presque comme le compilateur devrait me donner un autre avertissement, quelque chose comme "task
est assigné mais sa valeur n'est jamais utilisée", d'ailleurs ce n'est pas le cas. En outre, cela rend le code moins lisible. J'utilise moi-même cette approche.fireAndForget
... alors je m'attends à ce qu'il ne soit plus référencé.La raison de l'avertissement est que WorkAsync renvoie un
Task
qui n'est jamais lu ou attendu. Vous pouvez définir le type de retour de WorkAsync survoid
et l'avertissement disparaîtra.En général, une méthode renvoie un
Task
lorsque l'appelant a besoin de connaître l'état du travailleur. Dans le cas d'un feu et oubliez, void doit être retourné pour ressembler à ce que l'appelant est indépendant de la méthode appelée.la source
Pourquoi ne pas l'envelopper dans une méthode asynchrone qui renvoie void? Un peu long mais toutes les variables sont utilisées.
la source
J'ai trouvé cette approche par accident aujourd'hui. Vous pouvez définir un délégué et attribuer d'abord la méthode async au délégué.
et appelle ça comme ça
...
J'ai pensé qu'il était intéressant que le compilateur ne donne pas exactement le même avertissement lors de l'utilisation du délégué.
la source
(new Func<Task>(AsyncOperation))()
bien que l'OMI soit encore un peu trop verbeux.