7
votes

C # Producteur / modèle de consommation

J'ai un code simple à un producteur / à deux consommateurs comme suit, mais la sortie indique que seul C2 prend la consommation. Y a-t-il des bugs dans mon code? xxx

La sortie est la suivante: xxx


2 commentaires

Pourriez-vous décrire ce que vous essayez exactement d'atteindre? Votre exemple semble un peu conforté, je ne peux donc pas déterminer du contexte ce que vous devez faire.


Bonjour SouthSouth, veuillez jeter un coup d'œil à ce producteur-consommateur Exemple , cela peut vous aider.


6 Réponses :


4
votes

À des fins de test, essayez d'ajouter un délai dans le code du consommateur. Il est peut-être le cas que la "consommation" est si rapide qu'un fil de consommation vide la file d'attente avant que l'autre thread de consommateur ait une chance.

(édition)

Comme je soupçonnais, ajouter un

thread.sleep (500);

À l'intérieur du fil du consommateur (pour simuler un long traitement de traitement) entraîne les deux threads utilisés.


0 commentaires

2
votes

Votre producteur appelle uniquement moniteur.PulsAll Lorsque le décompte de la file d'attente est égal à 1 qui ne sera pas très souvent car rien de substance ne se fait par le producteur, cela signifie que le premier fil de consommation à travers la porte est deequuer le premier Item, le deuxième thread de consommation ne verra aucun objet dans la file d'attente et frappe donc le moniteur.Wait, et l'impulsion ne se reproduira pas (probablement jusqu'à ce que tout sauf le dernier élément est laissé) de sorte que le deuxième fil s'asseoira infiniment .


1 commentaires

Lorsque le premier fil de consommation à travers la porte arrive à Dequeue, la file d'attente.Count devient 0 et la prochaine fois que le producteur s'effectue un élément, le PulsAll sera touché à nouveau. Je ne vois pas pourquoi le deuxième fil s'asseoir et attendre infiniment dans ce cas.



0
votes

fil d'ajout.sleep (500); Dans Consumer.comsume

Puis j'ai ce qui suit,

C2 COMSUMENTATION ARTICLE1 C1 Comsuming Item2 C2 COMSUMENTATION ARTICLE3 C1 comsuming item4 c2 comsuming item5 C1 Comsuming Item6 c2 comsuming item7 c1 comsuming item8 ..... La resule n'est pas incertaine après avoir ajouté le sommeil.


1 commentaires

Quel consommateur consomme quel article est incertain et je pense que cela ne serait pas en conflit avec le but de l'auteur.



6
votes

Tout d'abord, je ne peux pas reproduire votre problème, ici les deux threads consomment certains des éléments. Je suppose que votre machine est plus rapide mais ajoute du sommeil comme GW suggérera que cela résoudra cela. Ce que je suggérerais également, c'est que vous n'essayez pas de synchroniser le producteur, je veux dire que les articles de la file d'attente aussi vite que possible et laissent les consommateurs synchronisés pour voir qui gère chaque article. J'ai fait une modification rapide et il semble fonctionner correctement:

static void Main()
    {
        Object lockObj = new object();
        Queue<string> queue = new Queue<string>();
        Producer p = new Producer(queue);
        Comsumer c1 = new Comsumer(queue, lockObj, "c1");
        Comsumer c2 = new Comsumer(queue, lockObj, "c2");

        Thread t1 = new Thread(c1.consume);
        Thread t2 = new Thread(c2.consume);
        t1.Start();
        t2.Start();

        Thread t = new Thread(p.produce);
        t.Start();

        Console.ReadLine();
    }
}
public class Producer
{
    Queue<string> queue;
    static int seq;
    public Producer(Queue<string> queue)
    {
        this.queue = queue;
    }

    public void produce()
    {
        while (seq++ < 1000) //just testinng 15 items
        {
            string item = "item" + seq;
            queue.Enqueue(item);
            Console.WriteLine("Producing {0}", item);                
        }
    }
}

public class Comsumer
{
    Queue<string> queue;
    Object lockObject;
    string name;
    public Comsumer(Queue<string> queue, Object lockObject, string name)
    {
        this.queue = queue;
        this.lockObject = lockObject;
        this.name = name;
    }

    public void consume()
    {
        string item;
        while (true)
        {
            lock (lockObject)
            {
                if (queue.Count == 0)
                {
                    continue;
                }
                item = queue.Dequeue();
                Console.WriteLine(" {0} Comsuming {1}", name, item);
            }                
        }
    }
}


1 commentaires

Non, j'ai réellement testé le code d'origine et j'ai reçu des sorties de C1 et de certains de C2.



0
votes

J'ai couru votre code et j'ai eu des poussées de C1 faire la consommation et les poussées de C2. Vous voudrez peut-être simplement vérifier ce lien à partir de MSDN: Comment : Synchronisez un producteur et un thread de consommateur (Guide de programmation C #)


1 commentaires

L'article a des bugs dans sa mise en œuvre suggérée. Faites défiler jusqu'à la section Commentaires de l'article lié pour les voir.



0
votes

Je pense que votre but est d'avoir plus d'un des threads de consommation de travail "en parallèle". Mais votre code est faible efficace. Les deux threads consommés fonctionnent essentiellement de manière séquentielle. Le code de travail réel doit être mis en dehors de la serrure afin que les deux threads de consommation puissent être exécutés en véritable parallèle. Cela améliore l'exécution si vous avez plusieurs cœurs ou même sur une seule machine à noyau en fonction de la propriété du travail. Sinon, il n'existe pas de point d'avoir plus d'un fil de consommation car de toute façon, tous les threads consomment en séquentiel.


1 commentaires

Merci Steve, avez-vous un exemple?