Autor Beitrag
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 :shock: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 09.10.13 05:43 
user profile iconGuaAck hat folgendes geschrieben Zum zitierten Posting springen:
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.