terran 0 Posted May 5, 2023 (edited) Hi! When I try to create a multiple threads in a DLL, they are probably running not in parallel, but sequential, and using only a single CPU core. Is it possible to make it to use multiple CPU cores? My "DLL" is a plugin for third-party app, and i have no idea what does the App with the DLL. library whatever; {$IFDEF FPC} {$MODE delphiunicode} {$ENDIF} {$R *.res} {$IFDEF WIN64} {$EXTENSION 'wdx64'} {$ENDIF} {$IFDEF WIN32} {$EXTENSION 'wdx'} {$ENDIF} {zzz$SetPEOptFlagszzz $160} uses SysUtils, Windows, Classes, contplug, RTLConsts; const cFieldsNames: array [0..0] of AnsiString = ('Data'); cFieldsTypes: array [0..High(cFieldsNames)] of Integer = (ft_Numeric64); DetectStr = 'EXT="JPG"'; type TLastInfo = record FileName: string; hash:int64; end; type TProcessFile = class private type TThreadx = class(TThread) private protected procedure Execute; override; public is_running:boolean; end; public threadx:array{[1..NUM_THREADS]} of tthreadx; function ProcessFile(const FileName: UnicodeString; FieldIndex, UnitIndex: Integer): Boolean; end; var RTL: TRTLCriticalSection; LastInfo: TLastInfo; ProcessFileVar:TProcessFile; var NUM_THREADS:integer=10; procedure TProcessFile.TThreadx.Execute; begin // dddddddd is_running:=false; end; function TProcessFile.ProcessFile(const FileName: UnicodeString; FieldIndex, UnitIndex: Integer): Boolean; var a:integer; is_finished:boolean; begin Result := false; try if LastInfo.FileName <> FileName then begin LastInfo := Default(TLastInfo); LastInfo.FileName := FileName; try setlength(threadx,NUM_THREADS); for a:=0 to NUM_THREADS-1 do begin threadx[a]:=TThreadx.Create(true); threadx[a].Priority:=tpLower; threadx[a].FreeOnTerminate:=false; threadx[a].is_running:=true; if threadx[a].Suspended then threadx[a].Resume; sleep(0); end; repeat is_finished:=true; for a:=0 to NUM_THREADS-1 do begin if threadx[a].is_running then is_finished:=false; sleep(0); end; until is_finished=true; for a:=0 to NUM_THREADS-1 do begin threadx[a].Free; end; finally end; Result := true; end; except Result := False; end; end; function ContentGetSupportedField(FieldIndex: Integer; FieldName: PAnsiChar; Units: PAnsiChar; MaxLen: Integer): Integer; stdcall; var Str: AnsiString; I: Integer; begin if FieldIndex in [0..High(cFieldsNames)] then begin StrCopy(Units,''); StrLCopy(FieldName, PAnsiChar(cFieldsNames[FieldIndex]), MaxLen - 1); Result := cFieldsTypes[FieldIndex]; StrLCopy(Units, PAnsiChar(''), MaxLen - 1); //for I := Low(cWebpEncodingString) to High(cWebpEncodingString) do // Str := cWebpEncodingString[I] + '|'; //if FieldIndex = 2 then // StrLCopy(Units, PAnsiChar(Str), MaxLen - 1); end else Result := ft_NoMoreFields; end; function GetValueW(FileName: PWideChar; FieldIndex, UnitIndex: Integer; FieldValue: PByte; MaxLen, Flags: Integer): Integer; var AFileName: string; begin Result := ft_FieldEmpty; AFileName := FileName; if Length(AFileName) > 256 then if Pos('\\', AFileName) > 0 then AFileName := '\\?\UNC\' + Copy(AFileName, 3, Length(AFileName) - 2) else AFileName := '\\?\' + AFileName; if not FileExists(AFileName) then Exit; try ProcessFileVar:=TProcessFile.Create; try if not ProcessFileVar.ProcessFile(AFileName, FieldIndex, UnitIndex) then Exit; except Exit; end; finally ProcessFileVar.Free; end; case FieldIndex of 0: PInt64(FieldValue)^ := LastInfo.hash; end; if FieldIndex in [0 .. High(cFieldsNames)] then Result := cFieldsTypes[FieldIndex] else Result := ft_fieldempty; end; function ContentGetValueW(FileName: PWideChar; FieldIndex, UnitIndex: Integer; FieldValue: PByte; MaxLen, Flags: Integer): Integer; stdcall; begin if (Flags and CONTENT_DELAYIFSLOW > 0) then begin Result := FT_DELAYED; Exit; end; EnterCriticalSection(RTL); try Result := GetValueW(FileName, FieldIndex, UnitIndex, FieldValue, MaxLen, Flags); finally LeaveCriticalSection(RTL); end; end; function ContentGetValue(FileName: PAnsiChar; FieldIndex, UnitIndex: Integer; FieldValue: PByte; MaxLen, Flags: Integer): Integer; stdcall; begin Result := ContentGetValueW(PWideChar(WideString(AnsiString(FileName))), FieldIndex, UnitIndex, FieldValue, MaxLen, Flags) end; procedure ContentGetDetectString(DetectString: PAnsiChar; MaxLen: integer); stdcall; begin StrLCopy(DetectString, PAnsiChar(DetectStr), MaxLen - 1); end; procedure ContentSetDefaultParams(dps: PContentDefaultParamStruct); stdcall; begin end; procedure DLLEntryProc; begin DeleteCriticalSection(RTL); end; exports ContentGetDetectString, ContentGetSupportedField, ContentGetValue, ContentGetValueW; //ContentSetDefaultParams; begin InitializeCriticalSectionAndSpinCount(RTL, 4000); DisableThreadLibraryCalls(HInstance); //Dll_Process_Detach_Hook := @DLLEntryProc; //DllProc := @DLLEntryProc; end. Edited May 5, 2023 by terran Share this post Link to post
David Heffernan 2345 Posted May 5, 2023 We don't know what your code does, and how it interacts with its host. Nobody can answer your question with the amount of information provided here. Share this post Link to post
Remy Lebeau 1394 Posted May 5, 2023 42 minutes ago, terran said: When I try to create a multiple threads in a DLL, they are probably running not in parallel, but sequential, and using only a single CPU core. Sounds like you (or the host app) are not actually creating new threads to call your DLL functions, instead you/it are just calling your DLL functions in the context of an existing thread. 42 minutes ago, terran said: Is it possible to make it to use multiple CPU cores? Anything is possible. 42 minutes ago, terran said: My "DLL" is a plugin for third-party app, and i have no idea what does the App with the DLL. Without seeing your actual DLL code, and without seeing some code/documentation about the host app's plugin interface, how do you expect anyone to help you? Share this post Link to post
terran 0 Posted May 5, 2023 (edited) I have added the code to the first post. The plugin interface: https://ghisler.github.io/WDX-SDK/contents.htm Sorry if I don't specified the info. Because if i sure that it is written correctly, there is no need to specify the code, and if it's impossible, then, too. Edited May 5, 2023 by terran Share this post Link to post
Dalija Prasnikar 1396 Posted May 5, 2023 Your thread class Execute method is basically empty. Is there any other code in there you didn't show? If not then that is the reason your code is running sequentially, as threads don't do anything. Also using lower priority for threads can make threads wait longer to get the CPU slice. Share this post Link to post
terran 0 Posted May 5, 2023 (edited) Soorry, probabiy it is executing too fast, so I could not notice that. And the slowest part cannot be paralleled. Edited May 5, 2023 by terran Share this post Link to post