Entwickler-Ecke
WinForms - Simulation Konsumenten-Produzenten-Problem -> Delegate|Event
markus490 - Di 08.09.15 23:15
Titel: Simulation Konsumenten-Produzenten-Problem -> Delegate|Event
Hallo zusammen,
ich möchte folgende Aufgabenstellung lösen:
Simulation eins Konsumenten-Produzenten-Problem.
Es werden zwei Threads erzeugt, wobei der eine der Konsument und der andere der Produzent ist.
Die auszuführenden Methoden produzieren() und entnehmen() werden in der Klasse "Lager" definiert und parallel gestartet.
Es sollen Ausgaben beim Füllen / Entnehmen, sowie bei einem vollen und leeren Lager in einer grafischen Oberfläche (ListBox) erfolgen.
Umgesetzt habe ich das wie folgt:
1. Klasse Lager angelegt, sowie die Methoden entnehmen / produzieren ausprogrammiert.
2. Grafische Oberfläche erzeugt, Screenshot (1) siehe unten.
3. Mittels Delegate + Event versuche ich ListBox-Einträge hinzuzufügen. An dieser Stelle erhalte ich aber eine Exception. Den Fehler kann ich nicht erkennen. Die parallelen Ausgaben auf der Konsole dienen lediglich zur Kontrolle. Screenshot (2) siehe unten
Für jegliche Hilfen bin ich mehr als dankbar.
Eine ausführliche Erklärung wie der Fehler ensteht ist mir sehr wichtig. Ich möchte das Problem verstehen.
Hier mein Quelltext:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164:
| using System; using System.Windows.Forms; using System.Drawing; using System.Threading;
namespace GPI13_E_2 { class Lager : Form { int bestand = 500;
public delegate void addListBoxEntry(int wert); public event addListBoxEntry addEntry;
public void entnehmen() { int anz; Random anzahl = new Random();
while (true) { anz = anzahl.Next(0, 100);
if (bestand < anz) { Console.WriteLine("<-> Entnahme nicht möglich! Bestand: " + bestand + " versuchte Entnahme: " + anz); } else { lock (this) { bestand -= anz; } Console.WriteLine("<-- Verkaufe Ware. \tAnzahl entnommener Waren: " + anz + "\tNeuer Bestand: " + bestand); if (addEntry != null) { addEntry(anz); } } Thread.Sleep(2000); } }
public void produzieren() { int anz; Random anzahl = new Random();
while (true) { anz = anzahl.Next(0, 3000);
if ((bestand + anz) > 10000) { Console.WriteLine("<-> Einlagerung nicht möglich. Kapazität (10.000) wird überschritten!)"); } else { lock (this) { bestand += anz; } Console.WriteLine("--> Produziere Ware. \tAnzahl Wareneingang: " + anz + "\tNeuer Bestand: " + bestand); if (addEntry != null) { addEntry(anz); } } Thread.Sleep(3000); } } }
class Program { static ListBox output = new ListBox(); static Button go = new Button(); static Lager la = new Lager();
static void startConsumerProducer(object sender, EventArgs e) { if (go.Text == "GO!") { go.Text = "Stopp!";
Thread en = new Thread(new ThreadStart(la.entnehmen)); Thread pr = new Thread(new ThreadStart(la.produzieren)); en.Start(); pr.Start(); } else { go.Text = "GO!"; } }
static void add(int wert) { output.Items.Add(wert); }
static void Main(string[] args) {
Font fontInventory = new Font("Calibri", 30, FontStyle.Bold);
output.Name = "outputListBox"; output.Location = new Point(50, 150); output.Size = new Size(900, 400); output.BackColor = Color.LightGray;
Label inventory = new Label(); inventory.Name = "outputLabel"; inventory.Location = new Point(250, 25); inventory.Size = new Size(500, 100); inventory.BackColor = Color.LightGreen; inventory.Font = fontInventory; inventory.TextAlign = ContentAlignment.MiddleCenter; inventory.Text = "Aktueller Bestand:\n";
go.Name = "goButton"; go.Location = new Point(0, 0); go.Size = new Size(50, 50); go.Text = "GO!"; go.Click += new EventHandler(startConsumerProducer);
Button clear = new Button(); clear.Name = "clearButton"; clear.Location = new Point(50, 0); clear.Size = new Size(50, 50); clear.Text = "Clear"; la.DesktopLocation = new Point(0, 0); la.ClientSize = new Size(1000, 600); la.Text = "Lagerbestand";
la.Controls.Add(output); la.Controls.Add(inventory); la.Controls.Add(go); la.Controls.Add(clear); la.addEntry += new Lager.addListBoxEntry(add);
Application.Run(la); } } } |
Screenshot (1) - GUI
Screenshot (2) - Exception
Moderiert von
Narses: Bilder als Anhänge hochgeladen
OlafSt - Mi 09.09.15 09:03
Außerdem ist es ganz, ganz mieser Stil, Controls als Variablenspeicher zu benutzen (if go.Text == "Start" ist so ein böses Ding).
Übersetze die Oberfläche mal ins italienische, dann wirst du verstehen ;)
markus490 - Do 10.09.15 13:29
Hätte ich mich doch schon eher hier gemeldet...
Vielen Dank euch beiden für die schnellen und kompetenten Rückmeldungen, das bringt mich wirklich ein großes Stück weiter. :-)
markus490 - Sa 12.09.15 22:59
Hallo zusammen,
ich habe eben versucht das Ganze in meinen obenstehenden Quellcode zu übernehmen.
Leider habe ich dabei noch Schwierigkeiten.
1. Um auf das ouput-Item zuzugreifen (Werte in die Listbox einfügen) muss es ja in der gleichen Klasse sein, in welcher ich die GUI erstellt wird. Korrekt? Sollte ich hierzu den gesamten Quellcode in eine Klasse legen?
C#-Quelltext
1:
| output.Items.Add("--> Produziere Ware. \tAnzahl Wareneingang: " + anz + "\t\t\tNeuer Bestand: " + bestand); |
2. Das Starten meiner Funktion findet wie folgt statt:
C#-Quelltext
1:
| Thread pr = new Thread(new ThreadStart(la.produzieren)); |
Soll ich darum noch den ganzen Spaß mit dem "invoke" basteln? Das ist doch bestimmt falsch...
markus490 - Mo 14.09.15 12:50
funktioniert :-) danke!
Die statischen Bestandteile sind mittlerweile auch alle entfernt.
Kein Designer, da es sich hier um eine Übungsaufgabe aus dem Studium handelt. Sonst hätte ich mir das Leben nicht unnötig schwer gemacht... ;-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!