![]() |
AW: TThread Suspend und Resume
Das Primitiv was du suchst, ist ein Mutex (zB. CriticalSection unter Windows) und eine
![]() Darauf aufbauend kannst du Warteschlangen implementieren. Dabei schläft der Thread so lange, bis er das nächste Element aus der Warteschlange nehmen kann. Auch so etwas sollte es in Threading-Bibliotheken fertig geben ... da kenne ich mich unter Delphi aber nicht aus. Nur wenn die Synchronisation ein Flaschenhals ist, muss man nach anderen Lösungen suchen, z.B. nicht-blockierende Algorithmen. |
AW: TThread Suspend und Resume
Da in dem Artikel darauf hingewiesen wird, dass Windows XP Condition-Variables nicht unterstützt, wir dieses aber noch unterstützen müssen, wäre ich daran interessiert wie du das dann machen würdest. Critical Sections (in Form von TCriticalSection) nutze ich bisher, um damit geteilte Daten zu synchronisieren.
Meistens Listen, bei denen ein Teilnehmer nur hinzufügt, der andere nur entfernt, und eben diese Operationen in einer Critical Section gegeneinander verriegeln. Das
Delphi-Quellcode:
aus meinem Beispiel wird in diesen Fällen oftmals auch ein
if FWaiting then Sleep(1)
Delphi-Quellcode:
.
if FList.Count = 0 then Sleep(1)
|
AW: TThread Suspend und Resume
Zitat:
![]() Im Prinzip könnte das so aussehen (Pseudocode, ungetestet):
Delphi-Quellcode:
Das Event dient quasi als Condition-Variable, die CS schützt die Queue bzw. hier nur den Zähler. Man kann und sollte das Ganze in eine Queue-Implementierung kapseln, wenn man damit sinnvoll arbeiten möchte.
var
cs : CriticalSection; ev : Event; // als auto-reset konfiguriert count : Integer; procedure producer() begin while (true) do begin //> Hier etwas sinnvolles machen! EnterCriticalSection(cs); // Einen Eintrag in die Queue einhängen: count := count + 1 // Hier ist die Bedingung immer erfüllst, // aber das muss nicht bei allen denkbaren Synchronisationsmustern so sein. if (count > 0) then setEvent(ev); // Aufwecken! LeaveCriticalSection(cs); end; end; procedure consumer() begin while (true) do begin EnterCriticalSection(cs); while (not (count > 0)) do begin // Wir verlassen die CS, damit der Producer was einhängen kann. LeaveCriticalSection(cs); WaitForSingleObject(ev); // Schlafen! EnterCriticalSection(cs); end; // Jetzt ist count > 0 und wir haben die CS! // Also können wir hier z.B. etwas aus der Queue aushängen: count := count - 1; // Bevor wir die CS verlassen, gucken wir noch mal, ob die Bedingung weiter erfüllt ist // und wecken gegebenenfalls noch den nächsten auf. if (count > 0) then setEvent(ev); LeaveCriticalSection(cs); //> Hier etwas sinnvolles machen! end; end; Disclaimer: Ich habe mich nicht eingehend mit den konkreten Windows Synchronisationsfunktionen befasst. Synchronisation ist schwer und fehleranfällig. Bitte auf Fehler/Bedenken hinweisen. |
AW: TThread Suspend und Resume
Interessant! SetEvent() und Co werde ich mir mal genauer anschauen müssen. Sieht erst mal nett aus. Danke dir!
|
AW: TThread Suspend und Resume
Zitat:
Delphi-Quellcode:
Was sind denn jetzt die Vor- und Nachteile von Sleep und WaitFor?
procedure TmyThreadObject.Execute;
var E: TmyAction; begin while not Terminated do begin if Actions.Count = 0 then begin Sleep(1000); Continue; end; E:= Actions[0]; // Do some Code end; end; EDIT: Die Vorgehensweise innerhalb der Execute-Methode erinnert mich inzwischen stark an die Entwicklung von Systemdiensten, die man auch in eine bedingte Schleife schickt. |
AW: TThread Suspend und Resume
Delphi-Quellcode:
Warum kein ...
if Actions.Count = 0 then begin
Sleep(1000); Continue;
Delphi-Quellcode:
:stupid:
while Actions.Count = 0 then begin
Sleep(1000); |
AW: TThread Suspend und Resume
Zitat:
|
AW: TThread Suspend und Resume
Mit anderen Worten:
Delphi-Quellcode:
Beinhaltet der Thread ein Sleep(1000); wartet dein Thread eine Sekunde. Gnadenlos und völlig egal, was um ihn herum für ein Zampano abgeht. Der Aufruf von Terminate in obigem Beispiel würde also eine Sekunde blockieren, weil der Thread nicht eher reagieren kann. Der Benutzer wiederum denkt: "Mal wieder abgestürzt" und läßt sich zu Chaos-Handlungen hinreißen.
procedure TForm1.FormClose(Sender: TObject)
begin MyThread.Terminate; MyThread.WaitFor; end; Besser wäre
Delphi-Quellcode:
Der Thread wartet nun auf den Event mit einem Timeout von einer Sekunde. Durch diesen Winkelzug hast du dein Sekunden-Sleep, bekommst den Thread aber sofort terminiert.
procedure TForm1.FormClose(Sender: TObject)
begin MyThread.Terminate; MyThread.SetEvent(MyThreadEvent); MyThread.WaitFor; end; |
AW: TThread Suspend und Resume
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz