Thema: Delphi Problem mit Task.Cancel

Einzelnen Beitrag anzeigen

Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.337 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