Мне нужно было создать расширение ISAPI для моего проекта.Я успешно создал объект TSession, который содержится в классе TSessionList = (TObject).Для очистки сеансов с истекшим сроком действия я создал поток очистки (потомок TThread), который периодически сканирует TSessionList и освобождает все сеансы с истекшим сроком действия.
Я создаю TSessionList и CleanupThread в главном блоке выполнения dpr.Что просто отлично.Но на самом деле я не уверен, куда положить уничтожение CleanupThread.Из документации я обнаружил, что расширение ISAPI должно экспортировать TerminateExtension, которое вызывается непосредственно перед выгрузкой расширения.Расширение Delphi ISAPI по умолчанию, конечно, экспортирует такую функцию.Итак, я «переопределил это» = экспортировал мой TerminateExtension, который освобождает мои объекты сеанса и затем вызывает по умолчанию ISAPIAPP.TerminateExtensionProc.
Вот как это выглядит:
function TerminateExtension(dwFlags: DWORD): BOOL; stdcall;
begin
DoneSessions;
Result:= ISAPIApp.TerminateExtension(dwFlags);
end;
exports
GetExtensionVersion,
HttpExtensionProc,
TerminateExtension;
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
InitSessions;
Application.CreateForm(TSOAPWebModule, SOAPWebModule);
Application.Run;
end.
CleanupThreadуничтожение выполняется в DoneSessions следующим образом:
begin
CleanupThread.Free;
SessionList.Free;
end;
CleanupThread является простым потомком TThread, поэтому не ищите ничего конкретного в его коде уничтожения.
Проблема в том, что TerminateExtension зависаеттолько в CleanupThread.Free.Дальнейшая отладка Я обнаружил, что зависание происходит в TThread.WaitFor.Я подозреваю, что должен быть какой-то тупик потока = рабочий поток ISAPI ожидает завершения моего расширения, которое ждет в TThread.WaitFor, чтобы основной поток получил сигнал (или любой другой).
Я знаю, что могПреодолеть эту ситуацию, вызвав CleanupThread.Terminate, затем использовать прямой WaitForSingleObject (или Multiple ???) и, наконец, освободить его.Но это звучит немного ... нестандартно.
Поэтому мой вопрос таков: как и когда я должен освободить (Terminate - WaitFor - Destroy) любые потоки поддержки в расширении ISAPI, чтобы избежать тупиковых потоков?
Кстати: я уже нашел то же самое в стандартной DLL.Если вы поместите какой-нибудь поток.WaitFor в процесс выгрузки dll, ваше основное приложение зависнет только при выгрузке библиотеки.Так что тот же самый вопрос / ответ, надеюсь, применим и здесь.