簡體   English   中英

如何在Delphi中的多個線程中加載DLL?

[英]How to Load a DLL in multiple threads in Delphi?

也許有些東西我錯過了,我不知道這里發生了什么。

我正在嘗試在TThread對象的多個實例中加載相同的DLL。

這是我的DLL代碼:

library MyCalcFor32;

uses
  SysUtils,
  Classes,
  uRunner in 'uRunner.pas';

Exports EVal;

{$R *.res}

begin
end.

這是uRunner.pas:

unit uRunner;

interface

uses SysUtils,
     Classes;

function EVal(Valor: WideString): WideString; stdcall; export;

implementation

function EVal(Value: WideString): WideString; stdcall; export;
begin
  Result := Value+' xxx';
end;

initialization

finalization

end.

這是加載DLL的程序:

procedure TfrmMain.FormCreate(Sender: TObject);
var I: Integer;
begin
  SetLength(Threads, 10);
  for I:= 0 to 9 do
  begin
    Threads[I] := TWorker.Create(Self.Handle, I+1, Memo1.Text, ExtractFilePath(ParamStr(0)));
  end;
end;


procedure TfrmMain.btnExecuteThreadsClick(Sender: TObject);
var I: Integer;
begin
  ClearMemos([MT1, MT2, MT3, MT4, MT5, MT6, MT7, MT8, MT9, MT10]);

  for I:= 0 to 0 do //to 9, for multiple
  begin
    if Threads[I].Suspended then
      Threads[I].Resume
    else
      ShowMessage('Thread already in execution');
  end;
end;

procedure TWorker.Execute;
var I: Integer;
    J: Cardinal;

    Ret: WideString;

    A,B,C: Extended;       
begin
  CoInitialize(nil);
  try
    LoadDll;

    while not Terminated do
    begin
      if not (Suspended or Terminated) then
      begin
        A := 310132041025;
        B := 17592186044416;
        C := 0;

        for I:= 0 to 10 do
        begin

          if (Terminated) then begin
            Break;
          end;

          for J:= 0 to 9999999 do
          begin

            if (Terminated) then begin
              Break;
            end;

            A:= Sqrt(A);

            if A <= 0 then begin
              A:= 310132041025;
            end
            else begin
              A:= Math.Power(A, 2);
            end;

            C:= C + (B-34 / 4);

            B:= B / 2;

            if B <= 0 then begin
              B:= 17592186044416;
            end;
          end;

          Ret := FEvalProcAddress(FEValValue);

          NotifyMainForm(Format('Evaluate %s, resulted in %s', [IntToStr(I), Ret]));
        end;
        Suspend;
      end;

      Sleep(5000);
    end;
  finally
    CoUninitialize;
  end;
end;  

procedure TWorker.LoadDll;
begin
  //GlobalLock.Enter;
  //try
    FDLLHandle := LoadLibraryA(PChar(FPathApp + 'MyCalcFor32.dll'));
  //finally
  //  GlobalLock.Leave;
  //end;

  if GetLastError <> 0 then
  begin
    NotifyTerminateThread;
  end
  else
  begin
    FEvalProcAddress := GetProcAddress(FDLLHandle, PChar('EVal'));

    if GetLastError <> 0 then
    begin
      NotifyTerminateThread;
    end;
  end;
end;

當我只有1個線程時,它工作得很好,但是當我使用多個線程時,它會引發以下異常:

System Error.  Code: 87.
Incorrect Parameter

注意:上面的代碼僅供復制;
我知道WideString + AnsiString問題。

您正在錯誤地執行錯誤檢查。 僅在函數失敗時才調用GetLastError 我希望您在成功的API調用之后調用GetLastError ,並且並非所有API調用在返回成功時都執行SetLastError(0) 因此,您將獲取一個過時的錯誤代碼,該代碼不適用於您進行的函數調用。

要檢查故障,對於這些功能,您需要檢查返回值。

  • LoadLibrary通過返回0報告失敗。
  • GetProcAddress通過返回nil報告失敗。

您必須仔細閱讀功能文檔,但這是一個非常常見的主題。 每個Win32 API函數可能會以不同的方式處理錯誤。 分別閱讀每個功能的文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM