AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit Task.Cancel

Ein Thema von stahli · begonnen am 21. Nov 2021 · letzter Beitrag vom 24. Nov 2021
Antwort Antwort
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#1

Problem mit Task.Cancel

  Alt 21. Nov 2021, 00:48
Hallo zusammen,

ich habe ein Problem, einen Task in einer komplexen Umgebung sicher abzubrechen.

In einem Testprojekt kann ich das Problem nicht nachstellen. Das reale Projekt (IDE-Experte) ist natürlich deutlich komplexer.

In dem Task wird zunächst synchronisiert über die VCL ein Wert ermittelt, dann verarbeitet und wieder synchronisiert in die VCL ausgegeben.
Im realen Projekt läuft die Datenverarbeitung in einem Interface-Objekt, dem der Task dazu für den evtl. Abbruch mit übergeben wird.

Wenn ich dort ein Sleep(50+) mit einbaue funktioniert der Abbruch auch.
Ohne Sleep wird die Exception von CheckCanceled nicht ausgelöst. Irgendwie scheint dann keine Zeit dafür zu sein.
Aber ein andauerndes Sleep ist natürlich bei sehr häufigen Schleifendurchläufen auch nicht praktikabel.

In dem Testprojekt habe ich die Berechnung jetzt noch nicht in ein eigenes Interface-Objekt ausgelagert.
Ansonsten ist das Grundprinzip etwa nachgestellt.

Das Testprojekt funktioniert allerdings mit und ohne Sleeps.

Warum mein reales Projekt nicht so funktioniert konnte ich noch nicht klären.
Wenn der Task nicht abgebrochen wird, dann mogelt sich der neue Task dazwischen, stellt die neuen Daten dar und dann werden die alten Daten weiter dargestellt.
Kann jemand das Problem anhand dieser etwas unscharfen Beschreibung nachvollziehen?


Delphi-Quellcode:
  procedure TForm1.ShowData;
  const
    MaxY = 100;
    MaxX = 5;
  var
    S: String;
  begin
    if Assigned(TestTask) and (TestTask.Status = TTaskStatus.Running) then
      begin
        OutputDebugString(PWideChar('-> ' + 'cancel'));
        TestTask.Cancel;
        OutputDebugString(PWideChar('<- ' + 'cancel'));
      end;

    TestTask := TTask.Create(
      procedure
      var
        Y, X: Integer;
        A : Array[1..MaxY] of Array[1..MaxX] of String;
      begin
        try
          TThread.Synchronize(nil,
            procedure
            begin
              OutputDebugString(PWideChar('-> ' + 'snc GetData'));
              S := Edit1.Text;
              OutputDebugString(PWideChar('<- ' + 'snc GetData'));
            end);

          OutputDebugString(PWideChar('-> ' + 'calc')); // CALCULATION
          for Y := 1 to MaxY do
            begin
              for X := 1 to MaxX do
                begin
                  A[Y, X] := S;
                  TTask.CurrentTask.CheckCanceled();
                  OutputDebugString(PWideChar('...calc... ' + IntToStr(Y) + ', ' +
                    IntToStr(X) + ' "' + S + '"'));
// Sleep(100);
                end;
            end;
          OutputDebugString(PWideChar('<- ' + 'calc'));

          TThread.Synchronize(nil,
            procedure
            var
              Y, X: Integer;
              S : String;
            begin
              OutputDebugString(PWideChar('-> ' + 'snc ShowData'));
              Memo1.Clear;
              for Y := 1 to MaxY do
                begin
                  for X := 1 to MaxX do
                    begin
                      S := A[Y, X];
                      OutputDebugString(PWideChar('...show... ' + IntToStr(Y) + ', ' +
                        IntToStr(X) + ' "' + S + '"'));
                      Memo1.Text := Memo1.Text + S + ' ';
// Sleep(100);
                    end;
                  Memo1.Text := Memo1.Text + sLineBreak;
                end;
              OutputDebugString(PWideChar('<- ' + 'snc ShowData'));
            end);
        except
          on EOperationCancelled do
            Exit;
        end;
      end);
    TestTask.Start;
  end;
Angehängte Dateien
Dateityp: zip TestTask.zip (3,49 MB, 5x aufgerufen)
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (21. Nov 2021 um 00:52 Uhr)
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#2

AW: Problem mit Task.Cancel

  Alt 21. Nov 2021, 03:56
Vielleicht eine dumme Antwort. (Wenn ja vergiß es einfach)
Unter umständen erstellst du irgendwo einen Deadlock schon mal mit TThread.Queue versucht an der stelle wo dein Problem auftritt?

Zitat:
Queue bewirkt, dass der in AMethod festgelegte Aufruf im Haupt-Thread asynchron ausgeführt wird, und verhindert somit Multithread-Konflikte.
Ich hatte zumindest ein ähnliches Problem in meiner TAudioVolume Componente.

Geändert von venice2 (21. Nov 2021 um 04:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Problem mit Task.Cancel

  Alt 21. Nov 2021, 09:13
Ein Deadlock kann m.E. aktuell nicht vorliegen, da das Programm sich nicht aufhängt.
Lediglich der abzubrechende Task wird verspätet weiter bearbeitet.

Eine Queue wird mir wohl auch nicht helfen, da sich diese vermutlich noch schlechter unterbrechen lässt.

Danke aber dennoch.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Problem mit Task.Cancel

  Alt 21. Nov 2021, 16:09
Ich habe einen offenbar funktionierenden und akzeptablen Workarround gefunden.

Aus dem Thread rufe ich MyProjekt.DoAllUnits auf und dort für jede Unit.DoAllLines...
Nach jeder Unit führe ich jetzt ein Sleep(100) aus. Die Verzögerung hält sich somit in Grenzen und die hinfälligen Tasks wurden bisher immer bei mir abgebrochen.

Als Workarround ist das erst mal ok. Wenn jemand noch einen besseren Tipp hat oder einen grundsätzlichen Fehler erkennt, wäre ich natürlich für eine Info dankbar.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli (22. Nov 2021 um 11:10 Uhr)
  Mit Zitat antworten Zitat
Andreas13

Registriert seit: 14. Okt 2006
Ort: Nürnberg
711 Beiträge
 
Delphi XE5 Professional
 
#5

AW: Problem mit Task.Cancel

  Alt 22. Nov 2021, 15:05
Hallo Stahli,
Du könntest evtl. die auf Delphi-Treff https://www.delphi-treff.de/tipps-tr...ndung-beenden/ beschrieben Routine KillTask ausprobieren. Vielleicht hilft es Dir.
Gruß, Andreas
Grüße, Andreas
Wenn man seinem Nächsten einen steilen Berg hinaufhilft, kommt man selbst dem Gipfel näher. (John C. Cornelius)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Problem mit Task.Cancel

  Alt 24. Nov 2021, 10:24
Danke für den Tipp. Ich merke mir das mal vor, aber meine aktuelle Lösung scheint mir übersichtlicher zu sein.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Antwort Antwort


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 +1. Es ist jetzt 03:54 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