Autor |
Beitrag |
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Mi 02.10.13 22:30
Liebe Experten,
ich mache gerade eine Anwendung mit 2 Threads A und B (noch Windows XP, Delphi 7) mit folgendem geplanten Ablauf:
Thread A empfängt per Message Daten, bereitet sie auf und schreibt sie in einen Puffer. Wenn der Puffer voll ist, dann wartet A bis Platz ist. Bei erstem Eintrag in Puffer: Resume Thread B.
Thread B liest die Daten aus dem Puffer und verarbeitet sie. Wenn der Puffer leer ist, dann suspend.
Mein Problem liegt in dem "warten bis Platz". Das habe ich mit WaitForSingleObject(Semphore...) gemacht. Thread B macht ein ReleaseSemaphore, wenn der Puffer Platz hat. Das Problem: Während des WaitForSingleObjekt können neue Messages kommen, dann läuft Thread A neu an und setze ein zweites WaitForSingleObjekt ab. Die Folge ist mir nicht ganz klar, es führt aber dazu, dass B suspended ist und A in einem WaitForSingleObject hängt, also Deadlock.
Eigentlich ist eine Synchronisation dieser Art doch eine Standard-Aufgabe. Hat da jemand einen Tipp, gerne auch einen Hinweis auf ein Buch oder ein Tutorial zu diesem Thema?
(Wenn ich statt WaitForSingleObject eine Schleife "WHILE NOT B.suspended sleep(0)" nehme, dann geht es, aber das verbraucht (logisch) so viel CPU-Zeit, dass ich lieber alles in einen Thread packen sollte, ich will ja mehrere Kerne zur Zeitverbessung nutzen und nicht zum Heizen.)
Wäre schön, jemand hätte da eine Tipp, im Anhang ist ein Minimalprojekt mit einem TButton und einem TMemo zum Probieren.
Viele Grüße
GuaAck
Einloggen, um Attachments anzusehen!
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 03.10.13 00:36
Suspend und Resume sind ganz böse, da ist es absolut kein Wunder, wenn es damit Probleme gibt. Nimm lieber TEvent um zu signalisieren, dass der Thread weiter machen soll und lasse den gar nicht schlafen...
// EDIT:
Bei der Quelltextformatierung hatte ich eigentlich keine Lust mehr, aber ich habs dann doch mal ein wenig angepasst als Beispiel... siehe Anhang...
Für eine echte Jobverwaltung müsste da aber noch mehr passieren, das ist nur ein Beispiel für die Synchronisierungsmöglichkeiten...
Einloggen, um Attachments anzusehen!
Für diesen Beitrag haben gedankt: GuaAck
|
|
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Fr 04.10.13 23:46
Danke Jaenicke,
Du hast Dir viel Mühe gemacht, und es hilft mir.
Event ist viel langsamer als Semaphore, und da ich das Problem gerne allgemein gelöst hätte, habe ich die Semaphore angestrebt. Aber aktuell geht es mit TEvent nach Deinem Muster sehr gut.
Danke also,
Gruß
GuaAQck
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 05.10.13 08:31
Ein Semaphor sollte an der Stelle eigentlich genauso gehen, wenn man ihr genauso einsetzt wie ich das TEvent. Allerdings hätte ich jetzt nicht gedacht, dass TEvent dabei langsamer ist, ich hatte damit noch nie Probleme.
Der Unterschied ist weniger Event <--> Semaphor als vielmehr kein Suspend und Resume usw. mehr.
Für diesen Beitrag haben gedankt: GuaAck
|
|
GuaAck
Beiträge: 378
Erhaltene Danke: 32
Windows 8.1
Delphi 10.4 Comm. Edition
|
Verfasst: Di 08.10.13 21:27
a) Mit den Zeiten habe ich mich wohl einfach geirrt, ich habe jetzt keinen Unterschied zwischen Event und Semaphore mehr gefunden, beides ist schnell.
b) Es läuft alles bestens: Starten per Event, Fertig-Meldung per Message.
c) Erstaunlich: Auch meiner Test-Einkern-Maschine ist die Aufteilung der Aufgabe auf zwei Threads geringfügig schneller als ein einziger Thread. Wahrscheinlich gibt es irgendwo bei der Grafikausgabe Wartezeiten, die bei der Aufteilung durch den anderen Thread genutzt werden können.
Danke also nochmals,
Gruß
GuaAck
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 09.10.13 05:43
GuaAck hat folgendes geschrieben : | c) Erstaunlich: Auch meiner Test-Einkern-Maschine ist die Aufteilung der Aufgabe auf zwei Threads geringfügig schneller als ein einziger Thread. Wahrscheinlich gibt es irgendwo bei der Grafikausgabe Wartezeiten, die bei der Aufteilung durch den anderen Thread genutzt werden können. |
Der Unterschied ist, dass du nicht zwischendurch warten musst bis sich die GUI aktualisiert hat. Das hast du ja vermutlich mit Application.ProcessMessages gemacht und damit immer alle Messages abgearbeitet. Und das braucht relativ viel Zeit, insbesondere, wenn man das zu oft aufruft.
Mit Threads läuft das alles nebenbei.
|
|
|