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;