Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   System.Threading: Kann man einen Task / Threadpool beenden? (https://www.delphipraxis.net/183497-system-threading-kann-man-einen-task-threadpool-beenden.html)

Der schöne Günther 14. Jan 2015 20:17

System.Threading: Kann man einen Task / Threadpool beenden?
 
Es ist im Endeffekt die gleiche wie eine meiner ersten Fragen hier:
http://www.delphipraxis.net/173890-w...gewaltsam.html
Nur diesmal auf
Delphi-Quellcode:
System.Threading
bezogen:

Kann ich einen Task, im worst case-Szenario, richtig abbrechen? Richtig tot machen?

Ein einfaches Cancel() setzt vielleicht im Task-Objekt ein Flag, aber terminiert wird der entsprechende Thread dadurch nicht:
Delphi-Quellcode:
procedure justTaskingThings();
var
   myTask: ITask;
begin
   myTask := TTask.Run(
      procedure
      begin
         sleep(5000);
         WriteLn('Task finished');
      end
   );

   sleep(1000);
   WriteLn('cancelling task');
   myTask.Cancel();
end;
Erst schläft er sich noch richtig aus, dann wird die Zeile
Delphi-Quellcode:
WriteLn('Task finished');
ganz normal ausgeführt.
Ich dachte dann, es könnte helfen, explizit einen eigenen TThreadPool dafür auf zu machen und diesen dann zu beenden:

Delphi-Quellcode:
procedure justThreadingThings();
var
   myTask: ITask;
   pool: TThreadPool;
begin
   pool := TThreadPool.Create();
   try

      myTask := TTask.Run(
         procedure
         begin
            while True do TThread.Yield();
         end,
         pool
      );

      myTask.Wait(100);
      WriteLn('cancelling task');
      myTask.Cancel();
   finally
      WriteLn('destroying pool');
      pool.Free();
   end;
   Writeln('pool is closed');
end;
Diese Anwendung wird nie beendet werden da der TThreadPool-Destruktor ewig hängt denn er wird auf den blockierenden Thread warten.


Ich finde keine Lösung. Gibt es überhaupt eine?

Sir Rufo 14. Jan 2015 22:26

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Ja und Nein.
Ja, man kann einen Task beenden
Nein einen Sleep kann ich nicht unterbrechen.

Wie unterbreche ich einen Task:

Indem man den Status des aktuellen Tasks abfragt mit
Delphi-Quellcode:
TTask.CurrentTask.Status
Delphi-Quellcode:
procedure Foo;
begin
  TTask.Run(
      procedure
    begin
      // nur loslaufen, wenn kein Abbruch
      if not TTask.CurrentTask.Status = TTaskStatus.Canceled
      then
        begin

        end;
    end );

  TTask.Run(
    procedure
    var
      LFinished: Boolean;
    begin
      // Arbeiten bis Abbruch oder Fertig
      while not( TTask.CurrentTask.Status = TTaskStatus.Canceled ) or LFinished do
        begin

        end;
    end );
end;
Das sollte dann auch dein Problem lösen.

Falls es da immer noch Probleme gibt, dann schau dir mal die Fixes für die Threading-Unit an: Kuckst du auf SO (Hat mich ein paar graue Haare gekostet) ;)

Stevie 14. Jan 2015 23:10

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Warum sie kein CancellationToken eingebaut haben, ist mir echt unverständlich...
Sonst könnt man ja so nützliche Sachen machen.

Ich würd mir wohl nen eigenes "abbrechbares" Sleep bauen, was über
Delphi-Quellcode:
TTask.CurrentTask.Status
checkt, obs noch weiterpennen soll.

Der schöne Günther 15. Jan 2015 18:35

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Das mit dem Sleep war nur ein dummes Beispiel. Bei mir ist es ein WinAPI-Aufruf der unter Umständen auf ewig blockiert. Bislang habe ich ihn in einem neuen Thread ausgeführt und wenn er nach einer bestimmten Zeit nicht fertig war habe ich ihn geplättet.

Ich dachte ich könnte dafür vielleicht jetzt System.Threading statt einer Eigenlösung nehmen, aber anscheinend nicht :-(

Sir Rufo 15. Jan 2015 19:38

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1286626)
Das mit dem Sleep war nur ein dummes Beispiel. Bei mir ist es ein WinAPI-Aufruf der unter Umständen auf ewig blockiert. Bislang habe ich ihn in einem neuen Thread ausgeführt und wenn er nach einer bestimmten Zeit nicht fertig war habe ich ihn geplättet.

Ich dachte ich könnte dafür vielleicht jetzt System.Threading statt einer Eigenlösung nehmen, aber anscheinend nicht :-(

Ähm, ja, wenn der WinApi.Aufruf blockiert wird und nicht wiederkommt ... hast du dir gedacht, dass Emba da jetzt ein wenig Zauberpulver genommen und ein paar salbungsvolle Worte dabei gesprochen hat und dann wird das schon? :shock:

Nein, Zaubern gehört bei denen noch nicht dazu.

Und wenn ein WinApi-Aufruf blockiert, dann schaue ich auch bei der WinApi, wie man das lösen kann ;)

Der schöne Günther 15. Jan 2015 21:05

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Meine Geschichte zu erzählen, warum dieser Aufruf sich aufhängen kann und warum ich damit umgehen können muss führt zu weit.

Ich wollte noch nicht einmal Zauberpulver sondern nur wissen, wie man einen Task hart abbrechen kann. Und wie man einen Threadpool schließt wenn ein andauernder Task da drin ist.

Sir Rufo 15. Jan 2015 21:27

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1286635)
Meine Geschichte zu erzählen, warum dieser Aufruf sich aufhängen kann und warum ich damit umgehen können muss führt zu weit.

Ich wollte noch nicht einmal Zauberpulver sondern nur wissen, wie man einen Task hart abbrechen kann. Und wie man einen Threadpool schließt wenn ein andauernder Task da drin ist.

Niemand hat nach der Geschichte gefragt ... du hast das quasi ungefragt aus freien Stücken ohne Zwang erzählt. Nein, ich will es auch nicht tiefer im Detail wissen. Keine Angst.

Aber wenn du einen Thread hart gegen die Wand fahren musst, dann wirst du mit einem Framework, was die Verwendung von Threads abstrahiert nie niemals nicht besser damit fertig, denn dieses harte gegen die Wand fahren ist nicht möglich (oder sehr schwer und bringt dann dieses Framework eher aus dem Trab).

Mir geht es nur darum, dass du verstehst, warum du da kein Hexenwerk erwarten kannst.

Der schöne Günther 15. Jan 2015 22:43

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Alles klar. Abseits meiner spannenden Geschichte finde ich es trotzdem etwas doof, selbst ständig auf "Cancelled?" prüfen zu müssen, mir wäre lieber gewesen, der Pool (oder wer auch immer) killt den entsprechenden Thread einfach wenn man von außen sagt "Schluss jetzt"

Vielleicht habe ich auch einfach nur ein verdrehtes Weltbild.
Nicht auszudenken, was ich als Politiker anstellen würde...

Sir Rufo 16. Jan 2015 01:07

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Ja so ein Task kann genauso automatisch abgebrochen werden wie jede andere Methode. :roll:

Du schreibst gerade in dem Task eine große Datei, dann würgst du das von aussen ab, die Datei ist kaputt und dann fängt wieder das Geschrei an. Du bist der Programmierer und nur du kannst entscheiden, wann es sicher ist, die Aufgabe abzubrechen.

Wenn du eine Aufgabe in einem Thread killen möchtest, dann kannst du
Delphi-Quellcode:
System.Threading
nicht verwenden. So einfach ist das. Schreib dir einen eigenen ThreadPool wo dieses harte Abwürgen funktioniert und dann sind alle glücklich - bis zu dem Tag, wo man etwas abgewürgt hat, was man besser nicht gemacht hätte - aber die Funktion ist ja da, dann benutzen wir die doch. :)

Dejan Vu 16. Jan 2015 06:46

AW: System.Threading: Kann man einen Task / Threadpool beenden?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1286644)
Alles klar. Abseits meiner spannenden Geschichte finde ich es trotzdem etwas doof, selbst ständig auf "Cancelled?" prüfen zu müssen, mir wäre lieber gewesen, der Pool (oder wer auch immer) killt den entsprechenden Thread einfach wenn man von außen sagt "Schluss jetzt"[/SIZE]

Das wäre fein. Und kein Problem. Schreibe einfach einen Wrapper um die Win-API die
  • einen internen Konsistenzstatus pflegt
  • bei einem 'Schluss jetzt' kontrolliert abbricht
  • z.B. in einem eigenen Sleep auf das 'Schluß jetzt' reagiert (ebenso in einer IO-Operation etc.)


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:15 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz