#delphi #asynchronous #jpeg
#delphi #асинхронный #jpeg
Вопрос:
TTask все еще выполняется даже после вызова Cancel
.
У меня есть сетка, которую я прокручиваю стрелками клавиатуры, при каждом изменении строки я уничтожаю старое TAsyncImage (если таковое имеется) и создаю новое TAsyncImages для новой строки и загружаю изображения. Если я прокручиваю достаточно быстро, оказывается, что старые TTasks из уничтоженных TAsyncImages все еще выполняются и каким-то образом изменяют вновь созданные TAsyncImages.
type
TAsyncImage = class(TImage)
private
FTask: ITask;
FOnFinish: TNotifyEvent;
FOnLoaded: TNotifyEvent;
procedure SetOnFinish(const Value: TNotifyEvent);
procedure SetOnLoaded(const Value: TNotifyEvent);
public
destructor Destroy; override;
property Async: Boolean read FAsync write FAsync;
property OnThumbLoaded: TNotifyEvent read FOnLoaded write SetOnLoaded;
property OnFinish: TNotifyEvent read FOnFinish write SetOnFinish;
end;
implementation
{ TAsyncImage }
destructor TAsyncImage.Destroy;
begin
if Assigned(FTask) and (FTask.Status = TTaskStatus.Running) then
begin
FTask.Cancel;
CheckSynchronize;
end;
FPicture.Free;
inherited Destroy;
end;
procedure TAsyncImage.LoadFromJPEG(AFileName: string; Scale: TJPEGScale);
var
J: TJPEGImage;
begin
if FAsync then
begin
FTask := TTask.Run(
procedure
var
B: TBitmap;
J: TJPEGImage;
begin
J := TJPEGImage.Create;
B := TBitmap.Create;
try
J.LoadFromFile(AFileName);
TThread.Synchronize(nil,
procedure
begin
if Assigned(FOnLoaded) then
FOnLoaded(Self);
end
);
J.Scale := jsEighth;
B.Assign(J);
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
Exit;
TThread.Synchronize(nil,
procedure
begin
if Assigned(Picture) then
Picture.Assign(B);
end);
if TTask.CurrentTask.Status = TTaskStatus.Canceled then
Exit;
if Scale <> jsEighth then
begin
J.Scale := Scale;
B.Assign(J);
TThread.Synchronize(nil,
procedure
begin
if Assigned(Picture) then
Picture.Assign(B);
if Assigned(FOnFinish) then
FOnFinish(Self);
end);
end;
finally
J.Free;
B.Free;
end;
end
);
end
else
begin
J := TJPEGImage.Create;
J.LoadFromFile(AFileName);
if Assigned(FOnFinish) then
FOnFinish(Self);
J.Scale := Scale;
Picture.Assign(J);
J.Free;
end;
end;
Или, если есть какое-либо лучшее решение для асинхронной загрузки изображений.
Комментарии:
1. 2 идеи. 1 используйте
TThread.CreateAnonymousThread
вместоTTask.Run
. 2. используйте флаг, который виден потоку, для завершения потока.2. Предполагаемое решение нежизнеспособно. Принудительное завершение не является решением. Ищите другое решение.