有没有办法立即终止TTask?

时间:2019-03-27 05:29:34

标签: delphi asynchronous jpeg

即使调用Cancel,TTask仍在运行。

我有一个网格,我用键盘箭头滚动,每次更改行时,我都会销毁旧的TAsyncImage(如果有),并为新行创建一个新的TAsyncImages并加载图像。如果我滚动得足够快,看来被破坏的TAsyncImages中的旧TTasks仍在运行,并且以某种方式更改了新创建的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;

或者,如果有更好的异步加载图像的解决方案。

0 个答案:

没有答案