Multithread service, BackgroundWorker vs pool de threads?
J'ai un .NET 3.5 Service Windows. Je suis en essais avec une petite application qui vient dort fils après leur départ, par hasard timespans de 300 à 6500ms. J'ai plusieurs questions au sujet de cette question.
- Est
BackgroundWorker
vraiment destiné pour utilisation seulement dans les applications WinForms ou est-ce simplement absurde, comment exactement est-il à l'écoute à cet effet? - J'ai lu sur
ThreadPool
s dans cette question et cette une. Je ne suis pas sûr de savoir exactement combien il est un problème pour moi que le fils durer entre une demi-seconde, et quelques secondes. Est-ce une raison suffisante pour regarder ailleurs? - Suis-je mieux de juste de créer les threads d'arrière-plan moi-même?
De vie réelle, service de sondage la base de données pour une liste de demandes en attente, exécuter les threads pour chacune de ces demandes (limitée à un certain nombre de threads simultanés) et chaque fil sera de vérifier si certaines des données dans une base de données, récupérer s'il le fait, ou le télécharger à partir d'un API en continu, les stocker, et de renvoyer les données. Le téléchargement serait la partie qui consomme le plus de temps.
Je voudrais vraiment cette question pour .NET Framework 3.5, mais si il y a de mieux ou de moyens plus efficaces pour accomplir cette vertu .NET 4.0, je voudrais lire sur eux trop. Des liens avec plus d'informations sont également très appréciées.
Vous devez vous connecter pour publier un commentaire.
La valeur dans
BackgroundWorker
est qu'il peut élever sonProgressChanged
etRunworkerCompleted
événement sur le thread qui a créé son instance. Ce qui le rend très pratique dans les programmes qui ne peuvent pas soutenir sans filetage.Pour que cela fonctionne correctement, il est cependant nécessaire que le
SynchronizationContext.Current
propriété fait référence à une non-synchronisation par défaut du fournisseur. Un fournisseur qui est responsable pour le marshaling des appels à partir d'un thread à l'autre. L' .NET framework a deux fournisseurs qui sont facilement disponibles:System.Windows.Forms.WindowsFormsSynchronizationContext
etSystem.Windows.Threading.DispatcherSynchronizationContext
. Ces fournisseurs de gérer la synchronisation pour, respectivement, Winforms et WPF.Il y a un lien, Winforms et WPF sont à la fois des bibliothèques de classes qui ont un filetage problème. À la fois de mettre en œuvre des Interfaces graphiques basés sur Windows et les interfaces utilisateur graphiques sont fondamentalement thread-dangereux. Windows windows peut uniquement être mis à jour à partir du thread qui l'a créé. En d'autres termes, les fournisseurs de synchronisation existent parce qu'il y a un besoin urgent pour eux. Également remarquable, c'est qu'ils travaillent en profitant de la manière de l'INTERFACE utilisateur de threads de travail. Un thread d'INTERFACE utilisateur exécute le code dans un événement piloté par le moyen, le pompage d'une boucle de message pour recevoir des notifications. Le fournisseur de synchronisation peut injecter des appels à des gestionnaires d'événement à l'aide de ce mécanisme. Ce n'est pas un accident.
De retour sur le sujet, un service Windows n'a pas un tel établissement. Il ne dispose pas d'une interface graphique et ne pas installer un custom fournisseur de synchronisation. En tant que tel,
BackgroundWorker
fournit aucune fonctionnalité est utile dans un service. Sans la synchronisation personnalisée fournisseur, le fournisseur par défaut fonctionne tout simplement événements sur un pool de threads thread. Ce qui n'est pas utile, vous pouvez ainsi déclencher l'événement à partir de votre thread de travail. Récupérer les évènements à exécuter sur un autre thread spécifique est très difficile à réaliser, sauf si vous recréer le message mécanisme de boucle ou crochet dans les Winforms de plomberie et de créer une simulation de thread de l'INTERFACE utilisateur à l'aide d'une fenêtre invisible. Qui n'est pas rare btw.BackgroundWorker a été conçu pour simplifier l'interaction de la tâche de travail dans le thread d'arrière-plan avec l'INTERFACE utilisateur. Vous verrez la grande réponse lors d'un BackGroundWorker, ThreadPool et simplement le Fil à BackgroundWorker vs Thread d'arrière-plan
Je pense qu'il répond à la question :).
J'ai écrit un assez exhaustive, les différentes implémentations de l'asynchrone tâches en arrière-plan sur mon blog. Le résumé est: préférez
Task
; le second choix seraitBackgroundWorker
; et de n'utiliserThread
ouThreadPool.QueueUserWorkItem
si vous avez vraiment besoin à.Raisons: il est plus facile de détecter et de corriger les erreurs, et il est plus facile de synchroniser retour à une INTERFACE utilisateur.
Pour répondre à vos questions:
BackgroundWorker
fonctionne dans n'importe quel hôte, y compris les WinForms et WPF (et même ASP.NET!), parce que il est basé surSynchronizationContext
. Les services de Windows n'ont pas deSynchronizationContext
, mais vous pouvez utiliserActionThread
de la Nito.Async bibliothèque, qui est livré avec unSynchronizationContext
.Si j'ai lu votre question correctement, vous avez actuellement
Thread
s et envisagentThreadPool
etBackgroundWorker
. De ces choix, je recommandeBackgroundWorker
, mais si vous avez de la chance, l'utilisation de la nouvelleTask
classe .NET 4.0 (si vous installez Microsoft Rx, vous pouvez également utiliserTask
dans .NET 3.5).BackgroundWorker
, compte tenu d'unThreadPool
, mon propreThread
s, et/ouTask
sTask
s, alors; ils sont plus d'une "unité de travail", un concept qui fonctionne bien avec le pool de threads, alors queBackgroundWorker
etThread
sont de véritables fils.Certainement pas Backgroundworker pour un service
Vous devriez aller avec les Tâches dans le Système.Le filetage.Les tâches de l'espace de noms, pourrait également utiliser des tâches en Parallèle filetage exécution
http://msdn.microsoft.com/en-us/library/dd460717.aspx
Je cite: "à Partir avec la .NET Framework 4, le TPL est le moyen préféré pour écrire multithread et du code en parallèle."
Certaines lectures:
http://msdn.microsoft.com/en-us/library/dd997413%28VS.100%29.aspx
Commencer ici:
http://msmvps.com/blogs/brunoboucard/archive/2010/04/09/parallel-programming-task-oriented-parallel-part-1.aspx
http://msmvps.com/blogs/brunoboucard/archive/2010/05/18/parallel-programming-in-c-4-0-task-oriented-parallel-programming-part-2.aspx
http://msmvps.com/blogs/brunoboucard/archive/2010/11/06/parallel-programming-with-c-4-0-part-3.aspx
Plus d'exemples
http://www.dotnetcurry.com/ShowArticle.aspx?ID=489
http://www.dotnetfunda.com/articles/article984-parallel-compting-in-csharp-40-.aspx
Je pense que votre troisième choix est le meilleur. J'ai fait des choses similaires avec les services Windows en .Net 3.5 et a constaté que la création de mon propre fils était un bon chemin à parcourir, notamment avec des fils qui ont été interfaçage avec des services web.
- Je créer une instance de travail et de lui donner un rappel que les signaux du service lorsque c'est fait. Je magasin de prêt-à-exécuter les threads dans un
Queue
et les peler en fonction du nombre maximum de threads simultanés que je veux. Si tout ce qui vous intéresse est le nombre de services en cours d'exécution, vous pouvez garder une trace d'eux avec un simple compteur. Je préfère stocker chaque travail en cours d'instance dans unDictionary
gérés par le threadManagedThreadId
de sorte que je peux facilement le signal de chaque exemple, si je veux l'arrêter proprement. Il est également pratique pour l'interrogation des instances en cours pour vérifier l'état.