我需要爲我的項目創建有狀態的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卸載過程中,你的主要應用程序凍結只是在庫卸載。所以同樣的問題/答案有希望適用於此。