線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5630
推到 Plurk!
推到 Facebook!

DLL EnterCriticalSection與thread配合使用問題

尚未結案
sge
一般會員


發表:5
回覆:2
積分:1
註冊:2002-12-19

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-04-06 10:13:02 IP:61.64.xxx.xxx 未訂閱
請教一下各位高手    以下是我用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  #include #include #ifdef __cplusplus #define Exp7K extern "C" __declspec(dllexport) #else #define Exp7K __declspec(dllexport) #endif CRITICAL_SECTION critSec; int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH : InitializeCriticalSection(&critSec); break; case DLL_PROCESS_DETACH : DeleteCriticalSection(&critSec); break; case DLL_THREAD_ATTACH : break; case DLL_THREAD_DETACH : break; } return TRUE ; } WORD CALLBACK DoTest(WORD wBuf[], char sSend[], char sReceive[]) { char wIndex,wFlag WORD wAddr,wRetVal,wTimeOut; EnterCriticalSection(&critSec); ... ... ... (程式省略) End: LeaveCriticalSection(&critSec); return(wRetVal); } WORD CALLBACK DoWork(WORD wBuf[], char sSend[], char sReceive[]) { char wIndex,wFlag WORD wAddr,wRetVal,wTimeOut; EnterCriticalSection(&critSec); ... ... ... (程式省略) End: LeaveCriticalSection(&critSec); return(wRetVal); }
anpino
版主


發表:31
回覆:477
積分:231
註冊:2003-01-02

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-04-06 13:13:43 IP:218.32.xxx.xxx 未訂閱
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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-04-06 15:03:48 IP:61.64.xxx.xxx 未訂閱
謝謝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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-04-07 18:36:12 IP:218.32.xxx.xxx 未訂閱
引言: 謝謝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
系統時間:2024-05-07 0:09:32
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!