我有一個Delphi DLL,需要從我的主UI應用程序或工作線程調用。動態初始化並從TThread按需調用LoadLibrary一次
我不想在每次調用DLL時調用LoadLibrary/FreeLibrary。但是,我也不想在我的應用程序初始化部分加載它。因爲我可能在應用程序的生命週期中根本不使用DLL。
所以我需要的是第一個調用者(線程或主UI)來初始化和加載DLL。 該DLL將在最終化部分中卸載。我意識到我需要一些同步。所以我使用了關鍵部分,但我似乎無法使其工作。
只有一個線程應該嘗試並加載DLL。如果失敗,其他線程不應該嘗試一次又一次加載DLL。
如預期的那樣,同步是不工作!
有人可以建議爲什麼嗎?
MCVE:
program Project1;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
Classes;
const
MyDLL = 'MyDLL.dll';
type
TDLLProcessProc = function(A: Integer): Integer; stdcall;
var
DLLProc: TDLLProcessProc = nil;
DLLModule: HMODULE = 0;
DLLInitialized: Boolean = False;
DLLInitialized_OK: Boolean = False;
CS: TRTLCriticalSection;
procedure InitDLLByFirstCall;
begin
if DLLModule = 0 then
begin
if DLLInitialized then Exit;
EnterCriticalSection(CS);
try
if DLLInitialized then Exit;
DLLInitialized := True;
DLLModule := LoadLibrary(MyDLL);
if DLLModule = 0 then RaiseLastWin32Error;
DLLProc := GetProcAddress(DLLModule, 'Process');
if @DLLProc = nil then RaiseLastWin32Error;
DLLInitialized_OK := True;
finally
LeaveCriticalSection(CS);
end;
end;
end;
function DLLProcess(A: Integer): Integer;
begin
InitDLLByFirstCall;
if not DLLInitialized_OK then
raise Exception.Create('DLL was not initialized OK');
Result := DLLProc(A);
end;
type
TDLLThread = class(TThread)
private
FNum: Integer;
public
constructor Create(CreateSuspended: Boolean; ANum: Integer);
procedure Execute; override;
end;
constructor TDLLThread.Create(CreateSuspended: Boolean; ANum: Integer);
begin
FreeOnTerminate := True;
FNum := ANum;
inherited Create(CreateSuspended);
end;
procedure TDLLThread.Execute;
var
RetValue: Integer;
begin
try
RetValue := DLLProcess(FNum);
Sleep(0);
Writeln('TDLLThread Result=> ' + IntToStr(RetValue));
except
on E: Exception do
begin
Writeln('TDLLThread Error: ' + E.Message);
end;
end;
end;
var
I: Integer;
begin
InitializeCriticalSection(CS);
try
// First 10 thread always fail!
for I := 1 to 10 do
TDLLThread.Create(False, I);
Readln;
for I := 1 to 10 do
TDLLThread.Create(False, I);
Readln;
finally
DeleteCriticalSection(CS);
end;
end.
DLL:
library MyDLL;
uses
Windows;
{$R *.res}
function Process(A: Integer): Integer; stdcall;
begin
Result := A;
end;
exports
Process;
begin
IsMultiThread := True;
end.
「未按預期工作」是什麼意思?預期的行爲是什麼?觀察到的行爲是什麼?他們有什麼不同? –
請勿檢查「DLLModule = 0」。刪除'DLLInitialized_OK'。只有初始化完成後才設置'DLLInitialized'。 -1沒有真正嘗試。 – mghie
CS可以在線程執行之前銷燬。 –