Question

Mon application surveille un répertoire dans lequel les utilisateurs peuvent télécharger un fichier. Lorsqu'un nouveau fichier est détecté, il est ajouté à une file d'attente. J'ai une minuterie qui parcourt la file d'attente et détermine si le téléchargement du fichier est terminé. Si des fichiers sont terminés, il utilisera le plus récent et lancera une tâche en arrière-plan (à l’aide de BackgroundWorker).

Mon problème est que je ne sais pas comment gérer le minuteur lorsque la tâche en arrière-plan est en cours d'exécution. Par exemple, si le minuteur est défini sur 10 secondes et que l’agent d’arrière-plan fonctionne toujours, je souhaite qu’il ignore l’exécution du travail d’un autre agent jusqu’à sa prochaine itération.

De plus, les informations pour chaque tâche sont stockées dans la file d'attente (un contrôle ListView) et je transmets le ListViewItem au travailleur en arrière-plan. Je suis curieux de savoir si le fait de passer ListViewItem a des effets secondaires.

Merci!

Était-ce utile?

La solution

Vous pouvez stocker des fichiers prêts à être traités dans une autre file d'attente (comme une file d'attente < string >) et demander à BgWorker d'interroger en permanence cette file d'attente. Vous obtiendrez peut-être également de meilleures performances, moins de temps mort. Vous devrez protéger la file d'attente (avec Monitor) et demander à BgWorker d'utiliser Monitor.Wait lorsque la file d'attente est vide.

Pour vous faire une idée, recherchez la réponse de Marc Gravell sur cette question . .

Autres conseils

Vraiment difficile de répondre à cette question sans voir le code dont vous parlez. Cependant, si vous devez synchroniser plusieurs événements asynchrones (la détection d'un fichier est téléchargée, l'ajout à une file d'attente, le traitement de la file d'attente), je suggère de créer un seul BackgroundWorker qui effectue toutes les tâches. Ensuite, il est facile pour votre travailleur de tester l’état de chaque étape. J'éviterais de créer plusieurs threads et d'essayer de les synchroniser, c'est très très problématique.

Je ne voudrais pas non plus stocker d'informations de tâche en arrière-plan dans une structure de données d'interface utilisateur (comme un contrôle ListView). Créez un rappel ou un événement dans votre BackgroundWorker qui alertera l’UI quand elle doit afficher quelque chose.

La chose la plus simple que vous puissiez faire est de faire tout le travail (y compris la vérification du dossier) dans votre BackgroundWorker: Vérifiez si vous avez quelque chose à faire, si oui, faites-le, sinon utilisez Sleep (time) ou WaitOne (time ) pour suspendre le fil pendant un certain temps.

Je ne pense pas que vous ayez besoin d'une file d'attente thread-safe, car le dossier est de toute façon mis à jour de manière asynchrone. Vous n'avez donc besoin que d'un seul thread, mais , vous avez besoin d'un moyen de l'arrêter. C’est pourquoi AutoResetEvent.WaitOne (heure) serait préférable à Veille (heure) - vous pouvez signaler l’événement à partir du thread principal pour mettre fin plus tôt à votre travailleur d’arrière-plan.

Sur votre gestionnaire Timer.Tick, vérifiez le BackgroundWorker.IsBusy pour déterminer s’il est prêt ou non pour un autre travail. Sinon, il suffit de ne pas lui donner le travail et d’attendre le prochain tick.

Vous pouvez créer une file de threads dans laquelle vous placez des tâches à effectuer. Votre arrière-plan travaille en boucle pour retirer des éléments de la file d'attente et effectuer le travail. Certaines choses doivent être considérées:

  • La file d'attente doit être thread-safe et il est fort probable que vous souhaitiez que le travail en arrière-plan bloque si la file est vide et se réveille lorsqu'un élément devient disponible. Je suis sûr que quelqu'un a déjà fait une si belle file d'attente.
  • Les éléments que vous publiez dans la file d'attente seront traités dans un autre thread (le backgroundworker). Assurez-vous que cela est fait de manière sécurisée pour les threads (par exemple, ne publiez pas d'éléments dans la file d'attente que l'application principale et l'agent en arrière-plan modifieront)

Une autre approche plus simple consiste à

  • Mettre en file d'attente les éléments de votre application. Lancez le backgroundworker une première fois.
  • Lorsque vous obtenez l'événement indiquant que le travail d'arrière-plan est terminé, sélectionnez l'élément suivant dans la file d'attente et redémarrez-le avec cet élément.
  • Vous devez toujours vous soucier de la sécurité des threads. Lorsque vous avez envoyé un élément à l’arrière-plan, assurez-vous que seul celui-ci fonctionne (par exemple, si vous ne lui envoyez que des chaînes, envoyez-lui plutôt une copie de cette chaîne)

Je ne vous ai pas bien suivi sur le chronomètre. Si l'agent d'arrière-plan a terminé, vous devriez obtenir un événement et vous saurez qu'il est terminé. Inutile de recourir à une minuterie pour le vérifier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top