J'ai un objet qui nécessite beaucoup d'initialisation (1-2 secondes sur une machine costaud). Bien que une fois qu'elle soit initialisée, il ne faut que 20 millions de Milisecondes pour faire un "travail" typique
afin de l'empêcher d'être réinitialisé chaque fois qu'une application veut l'utiliser (qui pourrait être 50 fois une seconde ou non à Toutes les minutes dans l'utilisation typique), j'ai décidé de lui donner un emploi que et de le faire courir sur son propre fil, vérifiant pour voir s'il y a un travail pour cela dans le Que. Cependant, je ne suis pas tout à fait sûr de savoir comment faire un fil qui fonctionne indéfiniment avec ou sans travail. P>
Voici ce que j'ai jusqu'à présent, toute critique est accueillie p> Après la pensée: je pensais que je devrais peut-être tuer ce fil gracieusement insister de la laisser courir pour toujours, alors je pense que je vais ajouter un type d'emploi qui indique au fil de se terminer. Toutes les pensées sur la fin d'un fil comme celui-ci aussi apprécié. P> p>
6 Réponses :
vous besoin strud> à avec Ajouter comme: P> verrouillage code> de toute façon, vous pouvez donc que vous puissiez attendre code> et impulsion code>: lock(queue) {
queue.Enqueue(item);
// if the queue was empty, the worker may be waiting - wake it up
if(queue.Count == 1) { Monitor.PulseAll(queue); }
}
File d'attente classique, verrouillage et pulsation.
@WILL: AFAIK, le seul téléchargement pour PFX est un CTP - I.E. Non pris en charge B>. Dans 4.0 (actuellement bêta), alors oui: le TPL, etc., sera une donnée - mais nous obtenons toujours un lot b> de 2.0 questions ici ...
Mark, pouvez-vous développer un peu sur ce qui se passe avec le moniteur.wait? Cela semble très intéressant
@Neil - vrai, vrai; J'ai retenu cela de la question initiale, mais oui - un arrêt / drain serait bien.
À attendre code>, vous devez tenir la serrure; Lorsque vous appelez attendre code>, vous libérer i> la serrure et votre thread est placé sur la file d'attente en attente (pas la file d'attente prête - donc vous ne revenez pas à la vie même si le la serrure est disponible). une autre i> thread sera (à un moment donné) obtenant la serrure et appelez impulsion code> / pulseall code>; Cela déplace le (s) filetage (s) de la file d'attente en attente dans la file d'attente Ready, de sorte que lorsqu'elles libèrent le verrouillage, votre thread vient dos i> dans la vie, obtient la serrure (à nouveau) et continue. Avoir un sens?
@Neil - J'ai également couvert davantage de choses de sortie sur l'autre question (liée).
Bonne réponse Cependant, je comprends que le pouls et la pulsaire ont été considérés comme une erreur. Spécifiquement, vous pouvez manquer une impulsion si vous faites un lors d'un interrupteur de filetage du répartiteur de noyau.
Vous avez besoin d'une primitive de synchronisation, comme un WAITHANDLE (regardez les méthodes statiques). De cette façon, vous pouvez «signaler» le fil du travailleur qu'il y a du travail. Il vérifie la file d'attente et continue de fonctionner jusqu'à ce que la file d'attente soit vide, date à laquelle il attend que le mutex le signalait à nouveau. p>
Faire de l'un des éléments de travail soit une commande Quitter aussi, de sorte que vous puissiez signaler le fil du travailleur quand il est temps de quitter le fil p>
Dans la plupart des cas, j'ai fait cela assez similaire à la façon dont vous avez mis en place - mais pas dans la même langue. J'ai eu l'avantage de travailler avec une structure de données (en python) qui bloquera le thread jusqu'à ce qu'un élément soit mis dans la file d'attente, niant la nécessité de l'appel du sommeil. P>
Si .NET fournit une classe comme ça, je regarderais à l'utiliser. Un blocage de fil est bien meilleur qu'un fil filant sur les appels de sommeil. P>
Le travail que vous pouvez passer pourrait être aussi simple qu'un "null"; Si le code reçoit une nuls, il sait qu'il est temps de sortir du temps et de rentrer à la maison. P>
attrape le cadre parallèle . Il a un BlockingCollection
Les fils seront bloqués jusqu'à ce qu'un élément apparaisse dans la collection. Celui qui tourne à tour est l'obtenir (dépend de la CPU). J'utilise ceci maintenant et ça marche très bien. P>
Il présente également l'avantage de s'appuyer sur la SM pour écrire que des bits de code particulièrement désagréables où les threads multiples accèdent à la même ressource. Et chaque fois que vous pouvez obtenir quelqu'un d'autre pour écrire que vous devriez y aller. En supposant, bien sûr, ils ont plus de ressources techniques / essais et une expérience combinée que vous. P>
Voulez-vous dire que le CTP marqué "Ce CTP est uniquement à des fins de test."? Pas sûr que c'est une grande recommandation ... dans 4.0, bien - mais c'est bêta!
Si vous n'avez pas vraiment besoin d'avoir la sortie de thread (et que de continuer à garder votre application en marche), vous pouvez définir thread.isbackground à true et il se terminera lorsque toutes les fils non fondés. Will et Marc ont-ils les deux bonnes solutions pour la manipulation de la file d'attente. P>
J'ai implémenté une file d'attente de fond sans utiliser de type Ce n'est pas qu'il n'y a pas d'attente et de pulsation. Mais tout cela se passe à l'intérieur du travailleur de fond code>. Cela se réveille simplement chaque fois qu'une tâche est tombée dans la file d'attente, elle s'exécute jusqu'à ce que la file d'attente soit vide, puis se rendormir. P> Je suis loin d'un expert en filetage. Y a-t-il une raison de dégager avec pendant code> en boucle ou à la pulsation, ou en attente, ou, en effet, touchez code> objet code>. Et il semble fonctionner. (Par lequel je veux dire que cela a été dans les environnements de production manipulant des milliers de tâches par jour pour les 18 derniers mois sans aucun comportement inattendu.) C'est une classe avec deux propriétés significatives, une queue System.threading code> pour un problème comme celui-ci si vous utilisez un travailleur d'arrière-plan code> fera? P> P>
En général, je conviens que la classe des travendistes d'arrière-plan est très souvent un choix plus simple de gérer une tâche de base. Dans ce cas, je dois contester certaines de vos revendications. Vous utilisez des objets de threading: le mot clé code> est le sucre syntaxique pour system.threading.monitor.enter () code> et system.threading.monitor.exit () < / code>. Au lieu d'une boucle omnibue, votre gestionnaire d'événements de course à exécution d'exécution Backworker.RunworkerAsync () Code>. Je pense que la logique d'une attente / pouls tandis que la boucle pourrait être plus facile à suivre dans ce cas.
Assez juste. Cela me ressemble probablement simplement pour moi parce que je ne suis pas expérimenté avec attendre / pouls.