Управление анонимными потоками в 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
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.