DLL EnterCriticalSection與thread配合使用問題 |
尚未結案
|
sge
一般會員 發表:5 回覆:2 積分:1 註冊:2002-12-19 發送簡訊給我 |
請教一下各位高手 以下是我用VC做的DLL檔(省略一些東西),這個DLL提供許多函式(如Dotest)給BCB呼叫使用.在bcb程式,我用兩個Thread來呼叫DLL的Dotest()函式,由於我在Dotest()內的變數是共用的,所以兩個Thread同時呼叫時,傳回值會錯亂,因此我就在dll被使用時(DLL_PROCESS_ATTACH),初始一個Critical Section,而每個DLL的函式都加上EnterCriticalSection,函式結束前再呼叫LeaveCriticalSection,釋放Critical Section。如此即一個Thread執行完函式後,另一個Thread才可以執行,避免Thread在讀取函式時發生錯亂。
這個方法應該是沒有問題。
不過因為我在DLL有許多函式,而BCB也會開許多thread來讀取不同函式。如果是讀取同一個函式時用以上方法仍可行,但如果有thread讀取一個函式(如Dotest),而另一個Thread讀取另一個函式(DoWork),在加入EnterCritical Section時,它們也會發生Dotest執行後,才可以執行Dowork之情形, 所以如果呼叫越多的函式,thread仍然需等前一個函式執行完後,才可以再執行,效能會變差.(因為同一個Critical Section)。
原本想在多增加Critical Section.
一個dll的函式(如DoTest)被呼叫時,其它的Thread要再使用時,就要進入同一個Critical Section(EnterCriticalSection),如果有另一個Thread要呼叫不同的函式(如Dowork),就再建立另一個CriticalSection。 如此,呼叫相同函式時就不會發生衝突,呼叫不同的函式時也不會被相同的Critical Section所羇絆住。
我的想法是否不正確??
如果要加程式碼在DLL,我就有困難了,如何判斷使用的Critical Section在哪個DLL 函式上使用,如何增加另一個Critacal Sectoion.我試過許多方式都不行 不知有沒有更好的方式來實現,請不吝指教 我沒有在BCB的程式上作處理,是因為我提供的是DLL,不是BCB的程式,所以只想在DLL做處理 謝謝 void __fastcall T1Thread::Execute()
{
for(;;)
DoTest();
}
void __fastcall T2Thread::Execute()
{
for(;;)
DoTest();
} #include
|
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
sge您好,
請參考MSDN中Critical Section Objects的說明:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/critical_section_objects.asp 一個process可以有許多Critical Section,
您可以再做一個CRITICAL_SECTION critSec2;
引述您的部分程式並加入的結果如下: CRITICAL_SECTION critSec;
CRITICAL_SECTION critSec2; int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH :
InitializeCriticalSection(&critSec);
InitializeCriticalSection(&critSec2);
break;
case DLL_PROCESS_DETACH :
DeleteCriticalSection(&critSec);
DeleteCriticalSection(&critSec2);
break;
case DLL_THREAD_ATTACH :
break;
case DLL_THREAD_DETACH : break;
}
return TRUE ;
} WORD CALLBACK DoWork(WORD wBuf[], char sSend[], char sReceive[])
{
char wIndex,wFlag
WORD wAddr,wRetVal,wTimeOut; EnterCriticalSection(&critSec2); ...
...
... (程式省略) End:
LeaveCriticalSection(&critSec2);
return(wRetVal);
} -------------------------------
數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D
Programmers Guide
http://anpino.begin.8d8d.com 發表人 - anpino 於 2004/04/06 13:18:34
|
sge
一般會員 發表:5 回覆:2 積分:1 註冊:2002-12-19 發送簡訊給我 |
謝謝anpino的回答 這是個不錯的方法 這個問題只是舉例2個函式,但實際上我的DLL有大約70~80個函式,所以用這個方式來建立,好像有點浪費記憶體, 但沒關系,我應該可以在function被呼叫時再malloc or new一個新的Critical Section,如此應該可以解決 另外個問題想請教
Q1)
原本以為
TryEnterCriticalSection(&critSec);
是用來測式是否 CriSec這個Critical section在使用中,
不過在DLL compiler卻不認識,
我查MSDN
QuickInfo
Windows NT: Requires version 4.0 or later.
Windows: Unsupported.
Windows CE: Unsupported.
Header: Declared in winbase.h.
Import Library: Use kernel32.lib.
所以無法使用, 不知有沒有替代的函式使用 Q2)
我的DLL函式不是用 void __declspec(Dllexport) _stdcall DoTest(....)來匯出,而是用.Def檔來匯出,而在.def內都需定義一個序號
EXPORTS
DoTest @2
DoWork @3
不知有沒有函式可以取得這個序號? Q3)我在BCB用
ComThread=new TComThread(true);
來宣告一個Thread
當程式呼叫dll函式時 (聯結dll產生的.LIB, 靜態呼叫dll)
會進入到 dllmain()的 DLL_PROCESS_ATTACH ,
而Thread 被建立執行時也會進入 DLL_THREAD_DETACH
以上都沒問題
不過結束Thread時,卻不會進入
DLL_THREAD_DETACH 我用以下三種方式任一種來結束Thread(但我不確定Thread是否真結束)
ComThread->Terminate();
ComThread1->Free ();
delete ComThread
但BCB程式結束時,也會進入到
DLL_PROCESS_DETACH 謝謝
|
anpino
版主 發表:31 回覆:477 積分:231 註冊:2003-01-02 發送簡訊給我 |
引言: 謝謝anpino的回答 這是個不錯的方法 這個問題只是舉例2個函式,但實際上我的DLL有大約70~80個函式,所以用這個方式來建立,好像有點浪費記憶體, 但沒關系,我應該可以在function被呼叫時再malloc or new一個新的Critical Section,如此應該可以解決 另外個問題想請教 Q1) 原本以為 TryEnterCriticalSection(&critSec); 是用來測式是否 CriSec這個Critical section在使用中, 不過在DLL compiler卻不認識, 我查MSDN QuickInfo Windows NT: Requires version 4.0 or later. Windows: Unsupported. Windows CE: Unsupported. Header: Declared in winbase.h. Import Library: Use kernel32.lib. 所以無法使用, 不知有沒有替代的函式使用 TryEnterCriticalSection我查到的是: Client: Requires Windows XP, Windows 2000 Professional, or Windows NT Workstation 4.0. Server: Requires Windows Server 2003, Windows 2000 Server, or Windows NT Server 4.0. Header: Declared in Winbase.h; include Windows.h. Library: Use Kernel32.lib. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/tryentercriticalsection.asp 我的經驗裡,沒有用過TryEnterCriticalSection,所以並不知道有沒有替代函式。這需要其他高手來解答。抱歉。 Q2) 我的DLL函式不是用 void __declspec(Dllexport) _stdcall DoTest(....)來匯出,而是用.Def檔來匯出,而在.def內都需定義一個序號 EXPORTS DoTest @2 DoWork @3 不知有沒有函式可以取得這個序號? 我不清楚您為什麼要取得這個序號,也不清楚為什麼要用.Def寫dll。 但是, 若果您是為了除去vc與non-vc使用上的問題, 可以參考這篇文章: http://www.booksea.com/pcbook/c /12/chap12.htm Q3)我在BCB用 ComThread=new TComThread(true); 來宣告一個Thread 當程式呼叫dll函式時 (聯結dll產生的.LIB, 靜態呼叫dll) 會進入到 dllmain()的 DLL_PROCESS_ATTACH , 而Thread 被建立執行時也會進入 DLL_THREAD_DETACH 以上都沒問題 不過結束Thread時,卻不會進入 DLL_THREAD_DETACH 我用以下三種方式任一種來結束Thread(但我不確定Thread是否真結束) ComThread->Terminate(); ComThread1->Free (); delete ComThread 但BCB程式結束時,也會進入到 DLL_PROCESS_DETACH 您可以將FreeOnTerminate設為true。 我很少用borland的thread,因為我不清楚它(thread)是不是夠安全, 所以我都用傳統的api去寫,並用CloseHandle確實的將thread給free掉。 當然程式結束之後,所有程式new出來的東西都會被銷毀, 進入DLL_PROCESS_DETACH是很正常的。 > 謝謝 >>< face="Verdana, Arial, Helvetica"> ------------------------------- 數學系是內功很強(邏輯/分析) 資工系是招式很多(程式技巧) 就像令狐沖VS東方不敗:D Programmers Guide http://anpino.begin.8d8d.com |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |