2011-11-26 64 views
4

我正在考慮一些構建DLL的一些常見的東西我做的想法。有一件事我想檢查一下是否可能在DLL中運行一個線程。我確信我至少可以啓動它,並在終止時自動釋放它(並強制終止它的自我) - 我可以看到它不會有什麼問題。但是一旦我啓動它,我就不會看到如何繼續與它溝通(特別是阻止它),主要是因爲每次調用DLL都是唯一的(據我所知),但我也知道很少學科。是否可以啓動(並停止)DLL中的線程?

我已經看到,在某些場合,一個DLL可以在開始裝載,並在當不需要的話了年底發佈。我對這種方法沒有什麼知識或經驗,除了看到與之相關的東西外,甚至不能告訴你什麼或怎樣,我不記得。但這甚至可能嗎?

我知道有關ActiveX/COM,但是這不是我想要的東西 - 我想只是一個可以跨語言(特別是C#)一同使用的基本DLL。

此外,如果可能的話,那麼我將如何去從DLL做回調到應用程序?例如,當我啓動線程時,我很可能會分配一個函數(在EXE內部)作爲事件的處理程序(由DLL觸發)。

所以我猜我問的是 - 如何加載連續工作一個DLL,並釋放它,當我做完了 - 而不是根據需要調用DLL中的各個功能的簡單方法。在相同的情況下 - 我可以在DLL中分配變量或創建對象。我如何確保一旦我分配了該變量(或創建對象),我如何確保在下次調用DLL時變量或對象仍然可用?顯然,它需要一種機制來初始化/完成DLL(I.E.在加載DLL時創建DLL中的對象,並在卸載DLL時釋放對象)。最後,我會將DLL包裝到一個組件中,所以當組件的一個實例被創建時,DLL將被加載並在DLL中創建一個對應的線程,然後當組件被釋放,DLL被卸載。還需要確保如果有這些組件的示例2,那麼將爲每個組件加載2個DLL實例。

這是以任何方式與使用IInterface有關嗎?因爲我也有這方面的經驗。

無需直接與示例源代碼回答吧 - 給一個很好的教程鏈接將是巨大的。

+0

在最後一個音符在那裏,我的意思是,我不希望任何人花時間,並詳細回答這個問題,我知道這是一個大課題,我需要的是有人向我展示了一個教程,做到這一點,沒有使用ActiveX。 –

+2

啓動線程,您無法通信和控制是一個壞主意。 –

+0

事實上,這就是爲什麼我想知道如何在他們開始後與他們溝通。 –

回答

7

你正在尋找的基本模式是這樣的:

  1. EXE調用DLL中的函數。
  2. EXE根據需要傳遞參數。
  3. DLL執行工作,啓動線程,返回一個句柄。我的意思是,在鬆散的工作意義上,而不是意味着Windows句柄。
  4. EXE現在可以通過調用更多的函數,傳遞句柄來進一步與DLL通信。
  5. DLL可以與EXE通信,例如通過回調,只要EXE提供了回調。
  6. 當停止的時候,EXE調用一個DLL函數,傳遞句柄。在這一點上,DLL收拾整理。

句柄的後面是DLL需要跟蹤調用之間的任何狀態。從EXE的角度來看,這個手柄是不透明的。

即使使用像C這樣的非OOP語言,這種模式也可以正常工作。但是,使用OOP功能要容易得多。由於您希望跨越模塊邊界,因此使用接口而不是Delphi對象會更安全。如果你通過模塊邊界傳遞Delphi對象,那麼你只能傳遞對象的數據部分,而不能傳遞代碼部分。

使用接口時,由DLL返回的接口變量充當上面我編號列表中的句柄。它包含任何實例數據。使用接口可以實現可擴展性。

至於線程部分,你最好使用更高級別的線程庫而不是原始線程。我建議的圖書館是PrimožGabrijelčič的OmniThreadLibrary

關於您的編輯:

我會換一個組件內的DLL,所以創建組件的實例時,DLL將被加載和相應的線程將DLL內創建,然後當組件被釋放時,DLL被卸載。還需要確保如果有這些組件的示例2,那麼將爲每個組件加載2個DLL實例。

當您將DLL加載到進程中時,它只有一個實例。特別是如果你打算使用全局變量,每個全局變量只會有一個實例,無論你調用多少次LoadLibrary

+0

所以,爲了確保我理解正確:如果我在DLL中聲明瞭一個變量,並且我發送了一個調用到設置該變量的DLL,那麼下次我調用DLL中的另一個函數時,該變量仍將被分配爲最後一次調用的方式?我害怕嘗試不知道肯定是有可能的。 –

+0

如果您使用全局變量,當然。但你不想這樣做。至少因爲你有線程。因此將狀態存儲在句柄或接口後面的對象中。 –

2

我試圖張貼此作爲一個評論,但跑出來的字符:簡單的答案是肯定的,它應該是可能的。設計API使其同步且運行良好是另一回事。我通常進入TCP/IP網絡soap框進行跨平臺/語言交流,但特別是在您尋找異步操作的環境中。設計一個具有「開始」「停止」和「isReady」呼叫的服務並不難。

http://docwiki.embarcadero.com/VCL/en/Classes.TThread

你潛入境內,將允許競爭條件,需要一些聰明的檢查是有效的。請注意這一點並閱讀相關主題。

這裏的基礎上建立一個DLL: http://delphi.about.com/od/windowsshellapi/a/dll_basics.htm

下面是使用一個基礎。我已經離開德爾福一兩年了,否則我會掀起一個快速的例子,我沒有急於爲自己購買副本,但所有語言的原則都是一樣的。在線程和界面設計中,有很多Java/C#教程。

一般來說一個 「簡單」 的設置可能是:

類 - 對象WorkToBeDone - 布爾isRunning - 布爾的isReady - 程序停止; - 程序開始(工作); - function isReady():boolean;

你的線程將在結構while循環運行:

procedure start(work) //inside new thread 
begin 
    isRunning := true; 
    isReady := false; 

    while(isRunning) 
    begin 
     doIncrementalOperationOnWork(); 
     thread.yield; 
    end; 
    work := thread.getWork(); 
    isRunning := false; 
    isReady := true; 

end; 

其粗草圖,但這個想法是外線來電可檢查,看它是否已準備就緒,並返回時,它是。我不確定你在做什麼,但這是一個「可能的」解決方案。正如德爾福所說的那樣,管理很多東西:每個CPU有16個線程是它們的「上限」。請注意這些限制。其他人可能會有更好的建議,這只是一個抽象模式,我用它將工作轉移到線程上,看起來簡單而直接。

+0

一些很好的觀點,但不是我正在尋找的答案,謝謝。 –

+2

每個cpu限制16個線程。你可以解釋嗎? –

+0

@DavidHeffernan,來自上面鏈接的文檔(http://docwiki.embarcadero.com/VCL/en/Classes.TThread):'跟蹤太多的線程會消耗CPU時間;建議的限制是單處理器系統上每個進程有16個活動線程。 –

0

線程存在於一個PROCESS內部。

進程運行可執行代碼:內置於.exe的代碼或從外部.dll加載的代碼。

的方法還可以運行代碼「遠程」 - 在單獨的過程碼,或甚至一個獨立的機 - 與像DCOM(微軟的COM/ActiveX),WCF(微軟.NET),RMI(爪哇)或CORBA技術/ IIOP(等等)。

既然你張貼在德爾福論壇,你最好的選擇可能是調查德爾福棱鏡:

http://edn.embarcadero.com/article/41598

如果你堅持使用舊版本的Delphi 7的,你最好的選擇可能是隻需堅持原始插座與遠程PC進行通信即可。

+0

只是爲了說明,因爲我們彼此之間:我不認爲我的例子是一個很好的設計選擇,這是對這個問題的技術答案。 –

+0

與遠程PC進行通信的問題在哪裏出現?我在兩個地方提到我不想故意使用ActiveX。而且我也不想離開Delphi7 - 我實際上是從Delphi 2010降級的。 –

+3

-1。這並沒有回答所問的問題,沒有提到任何關於「與遠程PC通信」的問題,也沒有在Delphi論壇(這是StackOverflow)中被問及,與使用Prism而不是Delphi無關。問題是關於Delphi DLL中的線程。 –

1

很多問題和有趣的日子打包學習經驗。

加載和卸載dll並不難,您添加一個名爲dllMain的函數。當被要求加載和卸載dll時,它是Windows使用的特殊人員。更多詳細的關於Delphi和線程,以及如何使用接口在delphi文章

About Delphi

充足。

當你得到一些更具體的問題時,我應該能夠提供幫助。然而作爲一名Delphi和C#程序員,我會用C#編寫這些東西,將它封裝到Com中,然後從Delphi中調用它。您將獲得更多幫助,查找更多教程,特別是在複雜場景中的語言支持會更好。

BackgroundWorker和線程池,更不用說並行擴展使得.net樂趣線程化。在德爾福,這只是痛苦的。

+0

這看起來很有希望,看着它... –

+0

在德爾福有線程的人有plentty。在C#中有很多很好的線程庫,使用interop對我來說聽起來不是一個好主意。 –

+0

也對我有用,但是如果我有選擇使用c#或Delphi的線程,我知道我會選擇哪一個。 –