2009-12-12 49 views
0

我正在爲MySQL嵌入式服務器編寫託管C++/CLI庫包裝程序。 mysql C庫要求我爲將要使用它的每個線程調用mysql_thread_init(),並且在使用它之後退出的每個線程都調用mysql_thread_end()。C++/CLI託管線程清理

調試任何給定的VB.Net項目我可以看到至少有七個線程;我想我的庫只會看到一個線程,如果VB沒有明確地創建工作線程本身(對此的任何確認?)。但是,我需要客戶端來訪問我的庫,以便能夠在需要時創建工作線程,因此我的庫必須在某種程度上具有線程意識。

我能想到的第一個選擇是在我的類中公開一些「EnterThread()」和「LeaveThread()」方法,因此客戶端代碼將在開始時顯式調用它們,並在退出其DoWork()方法。如果(1).Net不會「神奇地」創建用戶不知道的線程,並且(2)用戶足夠小心以在某種try/finally結構中調用方法,這應該可以工作。

但是,我不太喜歡讓用戶像那樣手動處理事情,我不知道我是否可以幫她處理這件事。在純Win32 C/C++ DLL中,我確實有DllMain DLL_THREAD_ATTACH和DLL_THREAD_DETACH僞事件,我可以根據需要使用它們調用mysql_thread_init()和mysql_thread_end(),但在C++/CLI中似乎沒有這樣的事情碼。爲了犧牲一些性能(我認爲不是很多),我可以使用TLS來檢測「使用新線程」的情況,但我可以想象沒有線程退出情況的機制。因此,我的問題是:(1).net能創建應用程序線程,而用戶不知道它們嗎?和(2)是否有任何機制可以使用類似於託管C++/CLI中的DLL_THREAD_ATTACH/DLL_THREAD_DETACH?

在此先感謝。

+0

我可以看到還有[ThreadStatic]屬性;也許和TLS一樣,如果句柄是nullptr我可以分配一個對象,它從構造函數調用init函數,它會在處理時調用結束線程代碼,但是不知道框架是否會從同一個線程調用IDisposable代碼,創建的,任何人都知道這個嗎? – 2009-12-12 11:21:16

回答

0

最根本的問題似乎是你的庫包裝沒有獲得足夠的可見性來查看它需要與底層MySQL庫正確通信的線程信息。在這種情況下,如果可能的話,我會嘗試直接解決根本問題。

在這種情況下,這意味着讓你的包裝完全知道和控制什麼線程接觸MySQL,什麼時候線程啓動,何時停止。

因此,例如,包裝庫中的頂級對象可以在內部啓動並擁有一個線程池,池中的每個線程在啓動時調用mysql_thread_init(),每個線程在關閉時調用mysql_thread_end()。這個線程池對於VB.net客戶端代碼是不可見的,但是在幕後,每個對你的包裝庫的調用都會切換到數據庫通信的一個線程池線程,然後將數據庫響應交給調用線程。

當客戶端破壞包裝器對象時,包裝器對象關閉並加入其內部線程池中的所有線程(每個線程在退出前都調用mysql_thread_end())。然後一切都被解釋了。

這可能是不可能的,具體取決於您的具體情況(每次調用包裝器時都會產生上下文切換成本;小心!),但我認爲這值得推薦。

如果這樣的事情對你不起作用,那麼你需要根據你提到的方法調用某種魔法系統巫術(我不是一個CLI人或者Windows人,所以我不能幫助你在那裏),或者你需要將責任傳遞給客戶。做後者的一個簡單方法就是說「包裝器對象只能用於創建它的線程中。「當然,當你的客戶不可避免地無法遵循這個約束時,你仍然面臨着新的一類錯誤...

+0

嗨,謝謝,Will。但是,整個想法是爲了避免轉換成本,因爲不可能有多個線程同時訪問MySQL. Appartment線程具有上下文切換性能,而這正是我想避免的。無論如何,我現在已經遷移到了SQLite,所以這都是學術的。 – 2010-03-16 15:29:24