您唯一的希望就是創建線程,然後從該線程加載DLL。因此,爲了儘可能清楚,創建線程,然後從該線程內執行的代碼中,調用LoadLibrary
來加載DLL。
VCL必須運行加載DLL的線程。 VCL初始化發生在DLL初始化期間,並確定哪個線程是VCL主線程。 VCL主線程是初始化加載DLL的線程VCL的線程。
由於在一個進程中你將有兩個GUI線程,兩個消息泵,你可能必須保持清醒的頭腦。顯示模式窗口涉及禁用兩個GUI線程上的窗口。
我不能確定這種通用方法(同一進程中的兩個GUI線程,其中之一是VCL線程)是否可以工作,從來沒有這樣做過。不過,我認爲這是一個很好的機會。
你也問一個非常具體的問題:
哪個線程將TThread.Synchronize(PROC:TThreadProc)發送的消息?
答案始終是初始化模塊的線程。所以對於一個可執行文件來說,這是該進程的主線程。對於DLL,初始化模塊的線程是調用LoadLibrary
的線程,該線程執行初始調用DllMain
的線程,該線程執行DLL單元的初始化代碼。這在RTL/VCL中是模塊的主線程。它是由System.MainThreadID
給出的ID。
爲了證明這一點,萬一你不聽我的話,這是一個小示範。
可執行
program DllThreading;
{$APPTYPE CONSOLE}
uses
Classes, Windows;
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TMyThread.Execute;
var
lib: HMODULE;
proc: procedure; stdcall;
begin
lib := LoadLibrary('dll.dll');
proc := GetProcAddress(lib, 'foo');
proc();
Sleep(INFINITE);
end;
begin
Writeln('This is the process main thread: ', GetCurrentThreadId);
TMyThread.Create;
Readln;
end.
DLL
library Dll;
uses
Classes, Windows;
type
TMyThread = class(TThread)
private
procedure DoStuff;
protected
procedure Execute; override;
end;
procedure TMyThread.DoStuff;
begin
Writeln('This is the thread which executes synchronized methods in the DLL: ', GetCurrentThreadId);
end;
procedure TMyThread.Execute;
begin
Writeln('This is the thread created in the DLL: ', GetCurrentThreadId);
Synchronize(DoStuff);
end;
procedure foo; stdcall;
begin
TMyThread.Create;
CheckSynchronize(1000);
end;
exports
foo;
begin
Writeln('This is the initialization thread of the DLL: ', GetCurrentThreadId);
end.
輸出
This is the process main thread: 2788
This is the initialization thread of the DLL: 5752
This is the thread created in the DLL: 6232
This is the thread which executes synchronized methods in the DLL: 5752
我錯過了某些東西,或者您正在訪問和運行方法,並在另一個線程中創建的Application對象上運行消息隊列。我認爲它應該早些時候墜毀.. –
@SertacAkyuz 我也這麼想過。顯然,VCL比我們考慮的更加靈活。:O 雖然,我仍然沒有嘗試使用帶有GUI客戶端的庫,只使用一個控制檯。可能我需要運行一個特殊的實驗來確定VCL是否仍然使用主線程的隊列。 – Delfigamer
@Delfigamer VCL如何做到這一點? VCL如何強制自己進入可執行文件所擁有的線程?它不能通過武力來實現。它需要可執行文件的合作。 VCL沒有任何過程主線程的概念。只有VCL線程,即初始化VCL的線程。 –