Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   OTL - Task2 durch Task1 überwachen (https://www.delphipraxis.net/199211-otl-task2-durch-task1-ueberwachen.html)

hschmid67 6. Jan 2019 16:44

OTL - Task2 durch Task1 überwachen
 
Hallo zusammen,

evtl. muss ich diese Frage ja besser in stackoverflow stellen, aber weil ich mit dem Forum hier so gute Erfahrungen gemacht habe, probiere ich es erstmal so. Wenn das unpassend sein sollte, bitte um kurze Rückmeldung.

Es geht um die OmniThreadLibrary. Ich möchte gerne einen Task durch einen anderen überwachen und ggf. neu starten, wenn er denn "abgestürzt" ist.

Meine Versuche gehen bisher so, dass ich zwei Variablen im Formular definiere, Task1 und Task2. Dann starte ich mit einem Button den Task1, der den zweiten Task2 starten soll, wenn Task2 denn noch (oder inzwischen wieder) nil geworden ist:

Delphi-Quellcode:
  Task1 := CreateTask(
    procedure(const mTask: IOmniTask)
    begin
      while not mTask.Terminated do
      begin
        Sleep(1000);
        // Task2 erzeugen und starten, wenn er denn noch nicht existiert
        if Task2 = nil then
        begin
          Task2 := CreateTask(
            procedure(const mTask: IOmniTask)
            begin
              while not mTask.Terminated do
              begin
                Sleep(1000);
              end;
            end)
            .OnTerminated(procedure(const mTask: IOmniTaskControl)
              begin
                Task2 := nil;
              end);
          Task2.Run;
        end;
      end;
    end)
    .OnTerminated(
      procedure(const mTask: IOmniTaskControl)
      begin
        Task1 := nil;
      end);
  Task1.Run;
Wenn ich jetzt versuche, zunächst den inneren Task zu beenden mit

Delphi-Quellcode:
Task2.Terminate(10000);
erhalte ich folgende Fehlermeldung:

"TOmniEventMonitorPool.Release: Monitor is not allocated for thread xxx."

Den äußeren Task kann ich mit

Delphi-Quellcode:
Task1.Terminate(10000);
problemlos beenden...

Zunächst verstehe ich nicht, was hier passiert. Vielleicht kann es mir jemand erklären? - Und dann wäre es schön, wenn mir jemand eine Lösung für mein Problem hätte :-) Ziel wäre es ja, dass der Task1 den Task2 überwacht und neu startet, sobald der Task2 - aus welchen Gründen auch immer - abgestürzt oder beendet ist.

Herzliche Grüße
Harald

Mimm 7. Jan 2019 09:26

AW: OTL - Task2 durch Task1 überwachen
 
Hallo!
IMO hat der zweite Task tatsächlich keinen Besitzer, da dieser im Kontext des ersten Task erstellt wird und nicht im Kontext des Main-Threads. Probier mal ob es eine Lösung ist, wenn du explizit einen EventMonitor erstellst und übergibst.

Folgender Link sollte helfen.
https://www.thedelphigeek.com/2009/1...erns-task.html

Gruß
Michael

hschmid67 7. Jan 2019 11:22

AW: OTL - Task2 durch Task1 überwachen
 
Hallo Michael,

vielen Dank für Deine Rückmeldung. Aber wenn ich das alles richtig verstehe, dann habe ich mit den beiden Formularvariablen Task1 und Task2 schon systemweite Variablen, die das Löschen des IOmniTaskControl verhindern sollten.

Und auch wenn ich folgende Zeile vor dem "Run" ergänze (ich habe eine TOmniEventMonitor aufs Formular gepackt), erhalte ich die besagte Fehlermeldung:

Delphi-Quellcode:
Task2.MonitorWith(OmniEventMonitor1);
Task2.Run;
Hmmm. Es könnte nach der Fehlermeldung zu urteilen schon daran liegen, aber ich weiß nicht, wie ich es besser/richtig mache...

Viele Grüße
Harald

bytecook 7. Jan 2019 14:40

AW: OTL - Task2 durch Task1 überwachen
 
Zitat:

Zitat von hschmid67 (Beitrag 1422733)
Hallo zusammen,

evtl. muss ich diese Frage ja besser in stackoverflow stellen, aber weil ich mit dem Forum hier so gute Erfahrungen gemacht habe, probiere ich es erstmal so. Wenn das unpassend sein sollte, bitte um kurze Rückmeldung.

Es geht um die OmniThreadLibrary.

... snip ...

Herzliche Grüße
Harald

Hallo Harald,

frag eher hier

https://en.delphipraxis.net/forum/32-omnithreadlibrary/

nach :) Nette url, nicht? :)

bytecook 7. Jan 2019 14:55

AW: OTL - Task2 durch Task1 überwachen
 
PS: Wenn du einen OmniThread freigeben willst, solltest du diesen via Task1.Stop() beenden, danach fTCCmd.WaitFor(INFINITE); ausführen, und danach Task1 auf nil setzen.
gerne mehr dazu, wenn ich vor einem vernünftigen Rechner sitze, und keine Doppelposts erzeuge...

hschmid67 7. Jan 2019 16:19

AW: OTL - Task2 durch Task1 überwachen
 
Hallo Peter,

vielen Dank erstmal. Das Forum in der englischsprachigen dp hatte ich tatsächlich nicht auf dem Schirm.

Den Rest Deiner Antwort verstehe ich nicht ganz.

Delphi-Quellcode:
Task.Terminate(10000);
müsste doch nach meiner Info den Task sanfter beenden als Task.Stop, was ihn ja ohne Zaudern abbricht, oder?

Aber: Es funktioniert, wenn ich statt

Delphi-Quellcode:
Task1.Terminate(10000);
folgenden Code verwende:

Delphi-Quellcode:
Task1.Stop;
Task1.WaitFor(10000);
Task1 := nil;

Task2.Stop;
Task2.WaitFor(10000);
Task2 := nil;
Das einzige, was unschön ist, dass bei der Lösung der Handler OnTerminated nicht aufgerufen wird.
Vielen Dank schon mal!


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:41 Uhr.

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