我需要为我的项目创建有状态的ISAPI扩展。我成功地创建了一个包含在TSessionList = class(TObject)中的TSession对象。为了清理过期会话,我制作了一个清理线程(TThread后代),它定期扫描TSessionList并释放所有过期的会话。ISAPI扩展TerminateExtension线程死锁
我在dpr主执行块中创建了TSessionList和CleanupThread。这很好。但实际上我不确定,在哪里销毁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(或多个???),并最终释放它。但这听起来有点......非标准。
因此,我的问题是:我应该如何以及何时释放(Terminate - WaitFor - Destroy)ISAPI扩展中的任何支持线程以避免线程死锁?
顺便说一句:我已经在标准的DLL中找到了相同的东西。如果你把任何线程.WaitFor在DLL卸载过程中,你的主要应用程序冻结只是在库卸载。所以同样的问题/答案有希望适用于此。