時,我有一個很大的德爾福2007年的項目,我用AsyncCall德爾福AsyncCalls死鎖終止的線程(COM + DLL定稿)
我已經提取,並在一個單一的控制檯應用程序測試的多線程代碼,一切工作正常。
我的Delphi 2007項目生成一個COM DLL,我有一些單元測試用C#寫的 - mstest調用DLL。
單元測試經常隨機掛起(測試通過),我發現它發生在AsyncCall單元 - finalizatoin部分釋放ThreadPool。
destructor TThreadPool.Destroy;
var
I: Integer;
Call: TInternalAsyncCall;
begin
FMaxThreads := FThreadCount; // Do not allocation new threads
FDestroying := True; // => Sync in this thread because there is no other thread (required for FAsnycCallHead.Free)
// Allow the threads to terminate if there is no task
for I := FThreadCount - 1 downto 0 do
FThreads[I].Terminate;
// Wake up all sleeping threads and keep them awake so they can terminate
SetEvent(FThreadTerminateEvent);
// Wait and destroy the threads
****Hangs here --------> for I := FThreadCount - 1 downto 0 do
****-------> FThreads[I].Free;
ReleaseAutoDeleteAsyncCalls;
// Clean up not yet released AutoDelete InternalAsyncCalls.
while FAsyncCallHead <> nil do
begin
Call := FAsyncCallHead.FNext;
CheckAutoDelete(FAsyncCallHead);
FAsyncCallHead := Call;
end;
CloseHandle(FThreadTerminateEvent);
CloseHandle(FWakeUpEvent);
CloseHandle(FMainThreadSyncEvent);
DeallocateHWnd(FMainThreadVclHandle);
DeleteCriticalSection(FAsyncCallsCritSect);
inherited Destroy;
end;
如果我刪除
for I := FThreadCount - 1 downto 0 do
FThreads[I].Free;
然後它工作正常。我不能在一個簡單的例子中重現這一點,也不能想到在終止時可能掛起線程的任何原因。
我相信這是非常相似,在這裏提出的問題:
http://qc.embarcadero.com/wc/qcmain.aspx?d=29843
如果一個線程停止時,它會調用由類ThreadExit:ThreadProc的和 ThreadExit調用與DLL_THREAD_DETACH的DLLEntryProc。一個進程中只有一個 線程可以一次處於DLL初始化或分離例程 中。
的問題是,一個COM + DLL定稿從 DLL_THREAD_DETACH運行,這樣的類:TThread.WaitFor將等待 indefinitly因爲線程將不會終止,因爲它無法處理 其DLL_THREAD_DETACH直到最終完成。
更新
我已經花了好幾天找出原因,並有一個變通是手動執行AsyncCall單元的定稿部分。
這與算法無關,因爲即使非常簡單的代碼也會導致com + dll中的問題。
下面是步驟來重現:
創建一個COM + DLL 創建具有下面的代碼的方法: 確保TestAsync叫,你會發現死鎖時,線程池(從AsyncCall)是清理線程。
procedure Test(int i: integer); cdecl;
begin
Exit;
end;
procedure TestAsyn;
var
t: IAsyncCall;
begin
t := AsyncCall(@Test, [0])
t.Sync;
end;
你需要找到一種方式來重現它在一個簡單的例子,或花一些時間調試自己的代碼,以找出問題。我們無法爲您調試我們無法訪問的代碼,爲了提供代碼,我們可以使用您需要提供的MCVE。確定如何提供人的過程通常可以解決問題。 –
你還需要花更多時間來嘗試在這裏發帖前自行解決問題。至少在最後一週,你每天至少要平均提出3個問題,這表明在發佈問題之前,很少有人努力解決問題(包括如何創建一個MCVE)。在你嘗試解決問題的其他方法已經耗盡之後,我們應該成爲「最後的手段」的地方。由於你最近發佈的許多問題都是重複的,這表明你很少或者根本沒有自己的研究。 –
你有什麼'TThread.Synchronize'在你的線程/任務的要求?這是釋放線程的情況下死鎖的一個主要原因 –