Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Управление анонимными потоками в Delphi: избегаем утечек памяти при закрытии приложения

Delphi , Компоненты и Классы , Потоки

Управление анонимными потоками в Delphi: избегаем утечек памяти при закрытии приложения

При работе с многопоточностью в Delphi важно правильно управлять потоками, чтобы избежать утечек памяти и других проблем, связанных с неправильным завершением потоков. Одна из таких проблем возникает при использовании анонимных потоков, созданных с помощью метода TThread.CreateAnonymousThread.

Проблема

Вопрос пользователя заключается в том, что при закрытии приложения с использованием кнопки "Закрыть" в заголовке окна возникает ошибка доступа (Access Violation at address $C0000005), которая указывается инструментом FastMM как утечка объектов TAnonymousThread. Это происходит из-за того, что в приложении используются анонимные потоки, созданные в событии OnTimer с помощью метода TThread.CreateAnonymousThread.

Решение

Пользователь нашел решение, заключающееся в создании обертки для анонимных потоков, которая позволяет корректно завершать их при освобождении. Обертка представляет собой класс TAnonumousThreadPool, который управляет списком потоков и предоставляет методы для их запуска и завершения.

type
  TAnonumousThreadPool = class(TObject)
  strict private
    FThreadList: TThreadList;
    procedure TerminateRunningThreads;
    procedure AnonumousThreadTerminate(Sender: TObject);
  public
    destructor Destroy; override; final;
    procedure Start(const Procs: array of TProc);
  end;

procedure TAnonumousThreadPool.Start(const Procs: array of TProc);
var
  T: TThread;
  n: Integer;
begin
  TerminateRunningThreads;
  FThreadList := TThreadList.Create;
  FThreadList.Duplicates := TDuplicates.dupError;
  for n := Low(Procs) to High(Procs) do
  begin
    T := TThread.CreateAnonymousThread(Procs[n]);
    T.OnTerminate := AnonumousThreadTerminate;
    T.FreeOnTerminate := True;
    FThreadList.LockList;
    try
      FThreadList.Add(T);
    finally
      FThreadList.UnlockList;
    end;
    T.Start;
  end;
end;

procedure TAnonumousThreadPool.AnonumousThreadTerminate(Sender: TObject);
begin
  FThreadList.LockList;
  try
    FThreadList.Remove(Sender);
  finally
    FThreadList.UnlockList;
  end;
end;

procedure TAnonumousThreadPool.TerminateRunningThreads;
var
  L: TList;
  T: TThread;
begin
  if not Assigned(FThreadList) then
    Exit;
  L := FThreadList.LockList;
  try
    while L.Count > 0 do
    begin
      T := TThread(L[0]);
      T.OnTerminate := nil;
      L.Remove(L[0]);
      T.FreeOnTerminate := False;
      T.Terminate;
      T.Free;
    end;
  finally
    FThreadList.UnlockList;
  end;
  FThreadList.Free;
end;

destructor TAnonumousThreadPool.Destroy;
begin
  TerminateRunningThreads;
  inherited;
end;

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

procedure TForm1.Button1Click(Sender: TObject);
begin
  FAnonymousThreadPool.Start([ // массив процедур для выполнения
    procedure{anonymous1}()
    begin
      // ...
    end,
    procedure{anonymous2}()
    begin
      // ...
    end;
    // ...
  ]);
end;

Важные моменты

  • При использовании анонимных потоков важно обеспечить их корректное завершение, чтобы избежать утечек памяти.
  • Класс TAnonumousThreadPool предоставляет удобный способ управления анонимными потоками, позволяя запускать и завершать их как единое целое.
  • При завершении приложения следует вызывать метод TerminateRunningThreads класса TAnonumousThreadPool, чтобы корректно завершить все потоки.

Альтернативные подходы

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

Подтвержденный ответ

Для управления жизненным циклом потоков важно не забывать, что при использовании CreateAnonymousThread параметр FreeOnTerminate установлен в True по умолчанию. Это означает, что после начала выполнения потока вы не можете управлять его жизненным циклом напрямую. Однако, можно установить FreeOnTerminate в False перед запуском потока, чтобы сохранить возможность управления.

Заключение

При работе с анонимными потоками в Delphi необходимо тщательно планировать их жизненный цикл, чтобы избежать ошибок и утечек памяти. Использование класса TAnonumousThreadPool является одним из эффективных способов решения этой задачи.

Создано по материалам из источника по ссылке.

Контекст заключается в управлении анонимными потоками в Delphi для предотвращения утечек памяти при закрытии приложения.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Потоки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2024-12-26 14:33:24/0.0033249855041504/0