J'utilise le code BlockingQueue posté in this question, mais j'ai réalisé que j'avais besoin d'utiliser une pile au lieu d'une file d'attente étant donné le fonctionnement de mon programme. Je l'ai converti pour utiliser une pile et renommé la classe au besoin. Pour les performances, j'ai supprimé le verrouillage dans Push, car mon code producteur est monothread.Comment faire Stack.Pop threadsafe
Mon problème est de savoir comment le thread travaillant sur le Stack (maintenant) thread sûr sait quand il est vide. Même si j'ajoute un autre wrapper thread sûr autour de Count qui se verrouille sur la collection sous-jacente comme Push et Pop, je suis toujours dans la condition de course que l'accès Count, puis Pop ne sont pas atomiques.
solutions possibles que je les vois (qui est préféré et suis-je manque tout qui fonctionnerait mieux?):
- fils de consommateurs attraper la InvalidOperationException lancée par Pop(). Pop() renvoie un nullptr lorsque _stack-> Count == 0, mais C++ - CLI n'a pas l'opérateur par défaut() ala C#. Pop() renvoie une valeur booléenne et utilise un paramètre de sortie pour renvoyer l'élément sauté.
Voici le code que je utilise en ce moment:
generic <typename T>
public ref class ThreadSafeStack
{
public:
ThreadSafeStack()
{
_stack = gcnew Collections::Generic::Stack<T>();
}
public:
void Push(T element)
{
_stack->Push(element);
}
T Pop(void)
{
System::Threading::Monitor::Enter(_stack);
try {
return _stack->Pop();
}
finally {
System::Threading::Monitor::Exit(_stack);
}
}
public:
property int Count {
int get(void)
{
System::Threading::Monitor::Enter(_stack);
try {
return _stack->Count;
}
finally {
System::Threading::Monitor::Exit(_stack);
}
}
}
private:
Collections::Generic::Stack<T> ^_stack;
};
"Pour les performances, j'ai supprimé le verrouillage dans Push, car mon code de producteur est à filetage unique." Qu'entendez-vous par là? Vous avez seulement un producteur? Votre code de producteur fonctionne-t-il en même temps que les consommateurs? – tony
Oui, je n'ai qu'un seul producteur et aucun code de producteur ne fonctionne en même temps que les consommateurs. Il fonctionne d'abord, puis exécute les multiples consommateurs avec le ThreadSafeStack produit par le producteur. –