Перейти к содержанию
Fire Monkey от А до Я
  • 0

Альтернатива для TTask


DirtyBorov

Вопрос

Хочу поделится своим модулем, некой альтернативой TTask, которой я пользуюсь уже довольно продолжительное время.  Возможно кому то будет полезно. 

AsyncTask это глобальная функция в модуле, которая возвращает интерфейс IAsyncTask. По этой причине нет нужды специально создавать объект и заботится о его удалении.

Пример использования:

procedure GetAsyncRequest(const aUrl: string);
var
  LResult: string;
begin

  AsyncTask.Run(
  procedure
  begin
    // это основной метод потока, он не синхронизирован. От сюда нельзя обращатся к визуальным компонентам 
    // или переменным вне функции без синхронизации (если необходимо)
    LResult := HttpRequest.Get(aUrl);
  end,

  procedure
  begin
    // Эта процедура выполнится при успешном завершении потока (без exception). 
    // Процедура синхронизированна, по этому тут можно обращатся к любым визуальным компонентам
    ShowMessage(LResult);
  end,

  procedure(E: Exception)
  begin
    // Эта процедура выполнится только если во время работы потока произошла ошибка
    ShowException(E);
  end,

  procedure
  begin
    // Эта процедура выполнится в любом случае (после завершения потока), в не зависимости была ошибка или нет
    ShowMessage(LResult);
  end
  );

// обратите внимание, что обязательно задать только первую процедуру, остальные можно не указывать или передать вместо них nil. Например так:
  AsyncTask.Run(
  procedure
  begin
    ...
  end,

  nil,

  procedure(E: Exception)
  begin
    ShowException(E);
  end);

 

Async.Task.pas.zip

Изменено пользователем DirtyBorov
Ссылка на комментарий

Рекомендуемые сообщения

  • 0
48 минут назад, DirtyBorov сказал:

По этой причине нет нужды специально создавать объект и заботится о его удалении.

Да и со старту нет необходимости заботиться об освобождении памяти для таска, достаточно описать Task таким образом: 

var LTask:ITask;

 

Изменено пользователем Сысоев Максим
Ссылка на комментарий
  • 0
36 минут назад, Сысоев Максим сказал:

Да и со старту нет необходимости заботиться об освобождении памяти для таска, достаточно описать Task таким образом: 

var LTask:ITask;

 

Да, я в курсе - это всего лишь уточнение. Тут тоже можно использовать например так:

var LTask: IAsyncTask;

LTask :=  AsyncTask;

LTask.Run (...);

...

LTask.Terminate; // досрочно завершаем поток

В ITask exception глушится, что не всегда хорошо. Тут его можно обработать очень просто, если есть нужда. Процедуры тут изначально синхронизированны и в подавляющем большинстве это как раз то что нужно - не нужно постоянно писать код синхронизации (хотя он и тривиален).

Сам же модуль был написан еще до появления ITask, так что я как то исторически привык использовать именно его. Однако у ITask есть свои преимущества и они неоспоримы. Это всего лишь альтернатива для некоторых случаев.

Ссылка на комментарий
  • 0
  • Модераторы

посмотрите реализацию TAnonymousThread 

type
  EAnonymousThreadException = class(Exception);

  TAnonymousThread<T> = class(TThread)
  private
    class var CRunningThreads: TList<TThread>;
  private
    FThreadFunc: TFunc<T>;
    FOnErrorProc: TProc<Exception>;
    FOnFinishedProc: TProc<T>;
    FResult: T;
    FStartSuspended: Boolean;
  private
    procedure ThreadTerminate(Sender: TObject);
  protected
    procedure Execute; override;
  public
    constructor Create(AThreadFunc: TFunc<T>; AOnFinishedProc: TProc<T>; AOnErrorProc: TProc<Exception>;
      ACreateSuspended: Boolean = False; AFreeOnTerminate: Boolean = True);

    class constructor Create;
    class destructor Destroy;
  end;

так универсальней получается

procedure TBitmapHelper.LoadFromStorage(AFile, AFileDef: string);
var
  _Thread: TAnonymousThread<TMemoryStream>;
begin
  _Thread := TAnonymousThread<TMemoryStream>.Create(
    function: TMemoryStream
    begin
      Result := TMemoryStream.Create;
      try
        Result.LoadFromFile(AFile);
      except
        try
          Result.LoadFromFile(AFileDef);
        except
          FreeAndNil(Result);
        end;
      end;
    end,
    procedure(AResult: TMemoryStream)
    begin
      if AResult.Size > 0 then
        if Assigned(self) then
          LoadFromStream(AResult);
      FreeAndNil(AResult);
    end,
    procedure(AException: Exception)
    begin
    end);
end;

 

AnonThread.zip

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...