Thread-safe file d'attente - mise en File / file d'attente
Tout d'abord, je vais vous expliquer un court scénario;
Comme un signal à partir de certains dispositifs déclencheurs, un objet de type d'Alarme est ajouté à la file d'attente. Dans un intervalle de temps, la file d'attente est cochée, et pour chaque Alarme dans la file d'attente, il déclenche une méthode.
Cependant, le problème je suis en cours d'exécution en est que, si une alarme est ajouté à la file d'attente alors qu'il est en cours de traversée, il déclenche une erreur de dire que la file d'attente a changé alors que vous l'utilisiez. Voici un peu de code pour montrer ma file d'attente, il suffit de supposer que les alarmes sont constamment inséré;
public class AlarmQueueManager
{
public ConcurrentQueue<Alarm> alarmQueue = new ConcurrentQueue<Alarm>();
System.Timers.Timer timer;
public AlarmQueueManager()
{
timer = new System.Timers.Timer(1000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DeQueueAlarm();
}
private void DeQueueAlarm()
{
try
{
foreach (Alarm alarm in alarmQueue)
{
SendAlarm(alarm);
alarmQueue.TryDequeue();
//having some trouble here with TryDequeue..
}
}
catch
{
}
}
Donc ma question est, comment puis-je faire de plus... "thread-safe"? De sorte que je ne vais pas courir sur ces questions. Peut-être quelque chose le long des lignes de, de la copie de la file d'attente à une autre file d'attente, de travail, puis dequeueing les alarmes qui ont été traitées à partir de l'original de la file d'attente?
edit: juste été informé de concurrente de la file d'attente, permettra de vérifier cette maintenant
OriginalL'auteur Shane.C | 2012-11-16
Vous devez vous connecter pour publier un commentaire.
Alternativement, vous pouvez utiliser:
Par l'article MSDN sur
ConcurrentQueue<T>.GetEnumerator
:Ainsi, la différence entre les deux approches se pose lorsque votre
DeQueueAlarm
méthode est appelée simultanément par plusieurs threads. À l'aide de laTryQueue
approche, vous avez la garantie que chaqueAlarm
dans la file d'attente n'exécuter qu'une seule fois; toutefois, le thread qui choisit d'alarme est déterminée non-déterministe. Leforeach
approche garantit que chaque course thread processus de toutes les alarmes dans la file d'attente (comme le moment où il a commencé à parcourir), résultant dans la même alarme en cours de traitement plusieurs fois.Si vous voulez traiter chaque alarme exactement une fois, et ensuite le supprimer de la file d'attente, vous devez utiliser la première approche.
Exactement. Aussi,
TryDequeue
retournefalse
lorsque la liste est vide, ce qui nous pousse à sortir de l'while
boucle.c'est assez chouette : ) va tester cela.
La première approche a un charme, exactement ce que je voulais. Suppose que c'est une de ces choses, une fois que vous savez ce que vous savez! Merci
Un plaisir de vous aider 🙂
OriginalL'auteur Douglas
Une raison quelconque vous ne pouvez pas utiliser
ConcurrentQueue<T>
merci pour l'aide
OriginalL'auteur hometoast
.Net a déjà un thread-safe file d'attente de mise en œuvre: jetez un oeil à ConcurrentQueue.
OriginalL'auteur jeroenh
Une meilleure façon de l'aborder, étant donné que chaque thread est en fait seulement le traitement d'une seule Alarme à la fois, serait de remplacer ce:
:
Il n'y a aucune raison pour obtenir une image complète de la file d'attente à tout moment, parce que vous ne soucient vraiment le suivant d'un processus au début de chaque cycle.
OriginalL'auteur Thought