J'ai vu dans WCF qu'ils ont l' [OperationContract(IsOneWay = true)]
attribut. Mais WCF semble un peu lent et lourd juste pour créer une fonction non bloquante. Idéalement, il y aurait quelque chose comme un vide statique non bloquant MethodFoo(){}
, mais je ne pense pas que cela existe.
Quel est le moyen le plus rapide de créer un appel de méthode non bloquant en C #?
Par exemple
class Foo
{
static void Main()
{
FireAway(); //No callback, just go away
Console.WriteLine("Happens immediately");
}
static void FireAway()
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("5 seconds later");
}
}
NB : Tous ceux qui liront ceci devraient se demander s'ils veulent réellement que la méthode se termine. (Voir la réponse principale n ° 2) Si la méthode doit se terminer, dans certains endroits, comme une application ASP.NET, vous devrez faire quelque chose pour bloquer et maintenir le thread en vie. Sinon, cela pourrait conduire à "feu-oubliez-mais-ne-exécutez jamais-réellement", auquel cas, bien sûr, il serait plus simple d'écrire aucun code. ( Une bonne description de la façon dont cela fonctionne dans ASP.NET )
la source
(new Action(FireAway)).BeginInvoke()
Task.Factory.StartNew(() => myevent());
de la réponse stackoverflow.com/questions/14858261/…Pour C # 4.0 et plus récent, il me semble que la meilleure réponse est maintenant donnée ici par Ade Miller: Le moyen le plus simple de faire un feu et d'oublier la méthode en c # 4.0
la source
FireAway
?Task.Factory.StartNew(() => FireAway(foo));
.Task.Factory.StartNew(() => FireAway(foo));
foo ne peut pas être modifié en boucle comme expliqué ici et iciPour .NET 4.5:
la source
Task.Factory.StartNew(() => FireAway(), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
selon blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspxPour ajouter à la réponse de Will , s'il s'agit d'une application console, lancez simplement un
AutoResetEvent
et unWaitHandle
pour l'empêcher de se terminer avant la fin du thread de travail:la source
WaitOne
est toujours bloquant etAutoResetEvent
fonctionnera toujoursWaitHandle
s, chacun avec son propreAutoResetEvent
et un correspondantThreadPool.QueueUserWorkItem
. Après cela justeWaitHandle.WaitAll(arrayOfWaitHandles)
.Un moyen simple consiste à créer et démarrer un thread avec lambda sans paramètre:
En utilisant cette méthode sur ThreadPool.QueueUserWorkItem, vous pouvez nommer votre nouveau thread pour faciliter le débogage. N'oubliez pas non plus d'utiliser une gestion complète des erreurs dans votre routine car toute exception non gérée en dehors d'un débogueur plantera brusquement votre application:
la source
La manière recommandée de le faire lorsque vous utilisez Asp.Net et .Net 4.5.2 est d'utiliser
QueueBackgroundWorkItem
. Voici une classe d'assistance:Exemple d'utilisation:
ou en utilisant async:
Cela fonctionne très bien sur les sites Web Azure.
Référence: Utilisation de QueueBackgroundWorkItem pour planifier des travaux en arrière-plan à partir d'une application ASP.NET dans .NET 4.5.2
la source
Appeler beginInvoke et ne pas attraper EndInvoke n'est pas une bonne approche. La réponse est simple: la raison pour laquelle vous devez appeler EndInvoke est que les résultats de l'appel (même s'il n'y a pas de valeur de retour) doivent être mis en cache par .NET jusqu'à ce que EndInvoke soit appelé. Par exemple, si le code appelé lève une exception, l'exception est mise en cache dans les données d'appel. Jusqu'à ce que vous appeliez EndInvoke, il reste en mémoire. Après avoir appelé EndInvoke, la mémoire peut être libérée. Dans ce cas particulier, il est possible que la mémoire reste jusqu'à ce que le processus s'arrête car les données sont conservées en interne par le code d'appel. Je suppose que le GC pourrait éventuellement les collecter, mais je ne sais pas comment le GC saurait que vous avez abandonné les données plutôt que de simplement prendre beaucoup de temps pour les récupérer. J'en doute. Par conséquent, une fuite de mémoire peut se produire.
Plus d'informations peuvent être trouvées sur http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx
la source
BeginInvoke
retourne un objet wrapper qui contient une référence à, mais n'est pas référencé par, l'objet qui contient les données de résultat réelles, l'objet wrapper deviendrait éligible pour la finalisation une fois que toutes les références à celui-ci ont été abandonnées.Près de 10 ans plus tard:
J'ajouterais la gestion des exceptions et la journalisation dans FireAway
la source
L'approche la plus simple .NET 2.0 et versions ultérieures utilise le modèle de programmation asynchrone (c'est-à-dire BeginInvoke sur un délégué):
la source
Task.Run()
exister, c'était probablement la manière la plus concise de le faire.