182 votes

BackgroundWorker vs background Thread

J'ai un style de question sur le choix de la thread d'arrière-plan de mise en œuvre, je devrais utiliser sur un formulaire windows app. Actuellement, j'ai un BackgroundWorker sur un formulaire qui a une infinie (while(true)) boucle. Dans cette boucle, j'utilise WaitHandle.WaitAny pour garder le fil de siestes jusqu'à ce que quelque chose d'intéressant se passe. L'un des événements les poignées j'attends, c'est un "StopThread" de l'événement afin que je puisse sortir de la boucle. Cet événement est signalé lors de mon substituée Form.Dispose().

J'ai lu quelque part qu' BackgroundWorker est vraiment destiné pour les opérations que vous ne voulez pas à la cravate de l'INTERFACE utilisateur avec et ont un fini fin - comme le téléchargement d'un fichier, ou le traitement d'une séquence d'éléments. Dans ce cas, la "fin" est inconnue, et seulement lorsque la fenêtre est fermée. Donc serait-il plus approprié pour moi d'utiliser un Thread d'arrière-plan au lieu de BackgroundWorker pour ce but?

387voto

Matt Davis Points 22019

Certains de mes pensées...

  1. Utilisation BackgroundWorker si vous avez une seule tâche qui s'exécute en arrière-plan et besoin d'interagir avec l'INTERFACE utilisateur. La tâche de regroupement des données et des appels de méthode pour le thread d'INTERFACE utilisateur sont gérés automatiquement par le biais de son événement à base de modèle. Éviter BackgroundWorker si...
    • votre assemblée n'ont pas ou n'interagit pas directement avec l'INTERFACE utilisateur,
    • vous avez besoin de le thread un thread de premier plan, ou
    • vous avez besoin de manipuler la priorité de thread.
  2. L'utilisation d'un pool de threads thread lorsque l'efficacité est souhaitée. Le pool de threads permet d'éviter les frais généraux associés à la création, le démarrage et l'arrêt des threads. Évitez d'utiliser le pool de threads si...
    • la tâche s'exécute pour la durée de vie de votre application,
    • vous avez besoin de le thread un thread de premier plan,
    • vous avez besoin de manipuler la priorité de thread, ou
    • vous avez besoin du fil à avoir une identité fixe (abandon, la suspension, la découverte).
  3. Utiliser le Fil de classe pour les longues tâches en cours d'exécution et lorsque vous avez besoin de fonctionnalités offertes par un modèle de thread, par exemple, le choix entre le premier plan et les threads d'arrière-plan, modifier la priorité de thread, le contrôle fin sur l'exécution du thread, etc.

95voto

ParmesanCodice Points 3339

De ma compréhension de votre question, vous utilisez un BackgroundWorker comme un pas de vis standard.

La raison pourquoi BackgroundWorker est recommandé pour des choses que vous ne voulez pas d'attacher le thread d'INTERFACE utilisateur est parce qu'il expose quelques belles événements lorsque vous faites Gagner des Formes de développement.

Des événements comme RunWorkerCompleted de signal lorsque le thread a accompli ce qu'il devait faire, et l' ProgressChanged événement pour mettre à jour l'interface graphique sur les fils de progrès.

Donc, si vous n'êtes pas faire usage de ceux-ci, je ne vois aucun mal dans l'utilisation d'un pas de vis standard pour ce que vous devez faire.

12voto

piers7 Points 1567

À peu près ce que Matt Davis a dit, avec les points supplémentaires suivants:

Pour moi, le principal facteur de différenciation avec BackgroundWorker automatique de l'ordonnancement de l'événement terminé par l' SynchronizationContext. Dans une INTERFACE utilisateur contexte, cela signifie que l'événement terminé feux sur le thread d'INTERFACE utilisateur, et peuvent donc être utilisés pour la mise à jour de l'INTERFACE utilisateur. C'est un facteur majeur de différenciation, si vous utilisez l' BackgroundWorker dans un contexte de l'INTERFACE utilisateur.

Des tâches exécutées par l' ThreadPool ne peuvent pas facilement être annulée (ce qui inclut ThreadPool. QueueUserWorkItem de délégués et d'exécution asyncronously). Ainsi, alors qu'il évite la surcharge de fil spinup, si vous avez besoin d'annulation soit utiliser un BackgroundWorker ou (plus probablement à l'extérieur de l'INTERFACE utilisateur) à lancer un thread et de conserver une référence à elle de sorte que vous pouvez appeler Abort().

11voto

Matt Points 2094

Aussi, vous êtes ligoté un thread threadpool pendant la durée de vie de l’ouvrier de fond, qui peut-être être d’intérêt qu’il y a seulement un nombre fini d'entre eux. Je dirais que si vous êtes seulement jamais créer le thread une fois pour votre application (et n’utilise aucun des éléments de travail d’arrière-plan) puis utilisez un thread, plutôt qu’un thread de pool de threads/backgroundworker.

10voto

Brett Ryan Points 4905

Vous savez, il est parfois plus facile de travailler avec un BackgroundWorker peu importe si vous utilisez Windows Forms, WPF ou quelle que soit la technologie. Neat partie sur ces gars-là est que vous obtenez un enfilage sans avoir à trop se soucier de l'endroit où vous êtes thread est en cours d'exécution, ce qui est idéal pour les tâches simples.

Avant d'utiliser un BackgroundWorker examiner en premier lieu si vous souhaitez annuler un thread (fermeture de l'app, l'utilisateur d'annulation) ensuite, vous devez décider si votre fil devriez vérifier pour les annulations ou si elle doit être poussée à l'exécution elle-même.

BackgroundWorker.CancelAsync() fixera CancellationPending de true mais ne rien faire de plus, c'est le nombre de threads responsabilité de vérifier en permanence ce, gardez à l'esprit également que vous pouvez vous retrouver avec une condition de concurrence dans cette approche où votre utilisateur a annulé, mais le fil terminé avant l'essai pour CancellationPending.

Thread.Abort() d'autre part, une exception sera levée dans l'exécution du thread, qui prévoit l'annulation de ce thread, vous devez être prudent sur ce qui peut être dangereux si cette exception a été soudainement soulevé au sein de l'exécution.

Le filetage des besoins très attentivement quelle que soit la tâche, pour certains plus de lecture:

En parallèle de la Programmation dans la .NET Framework Géré Threading Les Meilleures Pratiques

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X