AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

TThread Suspend und Resume

Ein Thema von Codehunter · begonnen am 14. Sep 2016 · letzter Beitrag vom 15. Sep 2016
Antwort Antwort
Seite 2 von 2     12
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#11

AW: TThread Suspend und Resume

  Alt 14. Sep 2016, 22:34
Das Primitiv was du suchst, ist ein Mutex (zB. CriticalSection unter Windows) und eine Condition-Variable. Der Mutex schützt den Zähler (und eventuell andere Datenstrukturen), auf der Condition-Variable kannst du schlafen. Das ist die Standard-Lösung für solche Probleme. So etwas mit Sleep oder Ähnlichem zu implementieren ist Frickelei (Sorry Medium ).
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.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.628 Beiträge
 
Delphi 2007 Enterprise
 
#12

AW: TThread Suspend und Resume

  Alt 14. Sep 2016, 23:55
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 if FWaiting then Sleep(1) aus meinem Beispiel wird in diesen Fällen oftmals auch ein if FList.Count = 0 then Sleep(1) .
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#13

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 01:15
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.
Events sehen in der Richtung gut aus. Da die aber beim Warten keine CS freigeben können und nicht zählen, muss man aufpassen mit Deadlocks und vergessenen Wake-ups. Semaphoren können dir das Zählen abnehmen, machen aber auch nicht alles einfacher ... und für jedes Zählen wechselt man in das Betriebssystem.

Im Prinzip könnte das so aussehen (Pseudocode, ungetestet):
Delphi-Quellcode:
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;
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.

Disclaimer: Ich habe mich nicht eingehend mit den konkreten Windows Synchronisationsfunktionen befasst. Synchronisation ist schwer und fehleranfällig. Bitte auf Fehler/Bedenken hinweisen.
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.628 Beiträge
 
Delphi 2007 Enterprise
 
#14

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 09:01
Interessant! SetEvent() und Co werde ich mir mal genauer anschauen müssen. Sieht erst mal nett aus. Danke dir!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.233 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 10:52
Die Execute-Methode wird nur einmal ausgeführt.
Ist die durch, dann ist der Thread fertig und kann nicht wieder neu gestartet werden.

Fazit: Eine Schleife einbauen
Grund: Das zweite Resume setzt den Thread nach dem "Suspend" fort und der Thread beendet sich dann, da er danach nichts mehr zu tun hat.

Aber ich würde eher vom Pausieren abraten und stattdessen irgendein "WaitFor" da hin tun und dann mit Events abeiten. (Thread wartet, bis Event gefeuert wird)
Also mit Pausieren funktionierts jetzt bei mir ganz gut, die Schleife war ja schon da:
Delphi-Quellcode:
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;
Was sind denn jetzt die Vor- und Nachteile von Sleep und WaitFor?

EDIT: Die Vorgehensweise innerhalb der Execute-Methode erinnert mich inzwischen stark an die Entwicklung von Systemdiensten, die man auch in eine bedingte Schleife schickt.
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden

Geändert von Codehunter (15. Sep 2016 um 10:56 Uhr)
  Mit Zitat antworten Zitat
dGeek
(Gast)

n/a Beiträge
 
#16

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 11:18
Delphi-Quellcode:
if Actions.Count = 0 then begin
      Sleep(1000);
      Continue;
Warum kein ...

Delphi-Quellcode:
while Actions.Count = 0 then begin
      Sleep(1000);
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.223 Beiträge
 
Delphi 10.4 Sydney
 
#17

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 12:22
Was sind denn jetzt die Vor- und Nachteile von Sleep und WaitFor?
Mit einem Event kannst Du von außen triggern, dass der nächste Durchlauf erfolgen soll. Bis dahin ruht der Thread.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
OlafSt

Registriert seit: 2. Mär 2007
Ort: Hamburg
284 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#18

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 12:51
Mit anderen Worten:


Delphi-Quellcode:
procedure TForm1.FormClose(Sender: TObject)
begin
   MyThread.Terminate;
   MyThread.WaitFor;
end;
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.

Besser wäre
Delphi-Quellcode:
procedure TForm1.FormClose(Sender: TObject)
begin
   MyThread.Terminate;
   MyThread.SetEvent(MyThreadEvent);
   MyThread.WaitFor;
end;
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.588 Beiträge
 
Delphi 10.4 Sydney
 
#19

AW: TThread Suspend und Resume

  Alt 15. Sep 2016, 14:03
Delphi-Quellcode:
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;
Ich hoffe Actions ist eine TThreadList?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 19:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf