Home All Groups Group Topic Archive Search About

What is wrong with this Producer-Consumer sample?

Author
10 Mar 2006 10:07 AM
Rene Ruppert
Hi,

I'm trying to implement the Producer-Consumer-Problem in C#.
Below is my code. The problem is, that the buffer always contains only one
element...it seems
that the Thread.Sleep() in the producer and in the consumers make the whole
app sleep
instead of only making the current thread sleep.
Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ErzVerbr
{
class Program
{
private const int MAX_ELEMENTE = 100;
private const int MAX_VERBRAUCHER = 2;
private static int anzElemente = 0;
private static Stack<int> puffer = new Stack<int>(MAX_ELEMENTE);
private static Object elementeVorhanden = "";
private static Object platzFrei = "";
static void Main(string[] args)
{
puffer.Clear();
Thread erz = new Thread(new ThreadStart(erzeuge));
erz.Name = "Erzeuger";
erz.Start();
Thread[] verbr = new Thread[MAX_VERBRAUCHER];
for (int i = 0; i < MAX_VERBRAUCHER; i++)
{
verbr[i] = new Thread(new ThreadStart(verbrauche));
verbr[i].Name = "Verbraucher " + (i + 1);
verbr[i].Start();
}
Console.ReadKey();
}
static public void erzeuge()
{
while (true)
{
lock (elementeVorhanden)
{
if (anzElemente == MAX_ELEMENTE)
{
System.Console.WriteLine("Warte auf Platz...");
Monitor.Wait(platzFrei);
System.Console.WriteLine("Platz verfgbar!");
}
Random rand = new Random();
int element = rand.Next(10, 20);
puffer.Push(element);
Console.WriteLine("Element erzeugt: " +
element + ", Puffer belegt: " +
(anzElemente + 1));
anzElemente++;
Monitor.PulseAll(elementeVorhanden);
Console.WriteLine("Sleep: " + Thread.CurrentThread.Name);
Thread.Sleep(rand.Next(10, 50));
}
}
}
static public void verbrauche()
{
while (true)
{
lock (platzFrei)
{
if (anzElemente == 0)
{
System.Console.WriteLine("Warte auf Elemente...");
Monitor.Wait(elementeVorhanden);
System.Console.WriteLine("Elemente vorhanden!");
}
int element = puffer.Pop();
anzElemente--;
Console.WriteLine("Verbraucht: " + element);
Random rand = new Random();
Monitor.PulseAll(platzFrei);
Console.WriteLine("Sleep: " + Thread.CurrentThread.Name);
Thread.Sleep(rand.Next(2000, 5000));
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ErzVerbr
{
class Program
{
private const int MAX_ELEMENTE = 100;
private const int MAX_VERBRAUCHER = 2;
private static int anzElemente = 0;
private static Stack<int> puffer = new Stack<int>(MAX_ELEMENTE);
private static Object elementeVorhanden = "";
private static Object platzFrei = "";
static void Main(string[] args)
{
puffer.Clear();
Thread erz = new Thread(new ThreadStart(erzeuge));
erz.Name = "Erzeuger";
erz.Start();
Thread[] verbr = new Thread[MAX_VERBRAUCHER];
for (int i = 0; i < MAX_VERBRAUCHER; i++)
{
verbr[i] = new Thread(new ThreadStart(verbrauche));
verbr[i].Name = "Verbraucher " + (i + 1);
verbr[i].Start();
}
Console.ReadKey();
}
static public void erzeuge()
{
while (true)
{
lock (elementeVorhanden)
{
if (anzElemente == MAX_ELEMENTE)
{
System.Console.WriteLine("Warte auf Platz...");
Monitor.Wait(platzFrei);
System.Console.WriteLine("Platz verfgbar!");
}
Random rand = new Random();
int element = rand.Next(10, 20);
puffer.Push(element);
Console.WriteLine("Element erzeugt: " +
element + ", Puffer belegt: " +
(anzElemente + 1));
anzElemente++;
Monitor.PulseAll(elementeVorhanden);
Console.WriteLine("Sleep: " + Thread.CurrentThread.Name);
Thread.Sleep(rand.Next(10, 50));
}
}
}
static public void verbrauche()
{
while (true)
{
lock (platzFrei)
{
if (anzElemente == 0)
{
System.Console.WriteLine("Warte auf Elemente...");
Monitor.Wait(elementeVorhanden);
System.Console.WriteLine("Elemente vorhanden!");
}
int element = puffer.Pop();
anzElemente--;
Console.WriteLine("Verbraucht: " + element);
Random rand = new Random();
Monitor.PulseAll(platzFrei);
Console.WriteLine("Sleep: " + Thread.CurrentThread.Name);
Thread.Sleep(rand.Next(2000, 5000));
}
}
}
}
}

Author
10 Mar 2006 10:54 AM
Jon Skeet [C# MVP]
Rene Ruppert wrote:
> I'm trying to implement the Producer-Consumer-Problem in C#.
> Below is my code. The problem is, that the buffer always contains only one
> element...it seems
> that the Thread.Sleep() in the producer and in the consumers make the whole
> app sleep instead of only making the current thread sleep.
> Maybe someone can help?

You're sleeping while still holding the lock, so anything else waiting
to acquire the lock will have to wait until you've finished sleeping.

See http://www.pobox.com/~skeet/csharp/threads/deadlocks.shtml (about
half way down) for a sample producer/consumer queue.

Jon
Are all your drivers up to date? click for free checkup

Author
10 Mar 2006 12:34 PM
Rene Ruppert
> You're sleeping while still holding the lock, so anything else waiting
> to acquire the lock will have to wait until you've finished sleeping.

Argl... thanks. That's it.

René

Bookmark and Share