如何在TThread中设置堆栈大小?

问题描述 投票:5回答:4

如何在TThread中设置自定义堆栈大小?我正在尝试重新引入TThread的构造函数,但它表示ThreadProc丢失了,但它仍然在System.Classes中。

type
  TThreadHelper = class helper for TThread
    constructor Create(const CreateSuspended: Boolean = False; const StackSize: Integer = 0); reintroduce;
 end;

{ TThreadHelper }

constructor TThreadHelper.Create(const CreateSuspended: Boolean; const StackSize: Integer);
begin
  Self.FSuspended := not Self.FExternalThread;
  Self.FCreateSuspended := CreateSuspended and not Self.FExternalThread;
  if not Self.FExternalThread then
  begin
    Self.FHandle := BeginThread(nil, StackSize, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, Self.FThreadID);
    if Self.FHandle = 0 then
    raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
  end
  else
  begin
    Self.FHandle := Winapi.Windows.GetCurrentThread;
    Self.FThreadId := GetCurrentThreadId;
  end;
end;

[[dcc32错误] Project5.dpr(29):E2003未声明的标识符: 'ThreadProc'

delphi delphi-xe6
4个回答
7
投票

我不知道,是否可以在创建线程后设置堆栈大小。也许SetThreadStackGuarantee会有所帮助?

您可以使用SetThreadStackGuarantee从头开始创建线程,但这非常复杂。我在这里使用BeginThread来解决。请注意,有几个Detours变体。我认为只有Detours是x64兼容的。

Cromis.Detours

我不知道为什么Embt不允许程序员指定堆栈大小,如果有人知道原因,这对我来说将非常有趣。


3
投票

根本无法使用unit IndividualStackSizeForThread; interface uses System.Classes, Cromis.Detours { http://www.cromis.net/blog/downloads/cromis-ipc/ }; type TThreadHelper = class helper for TThread constructor Create(CreateSuspended: Boolean; StackSize: LongWord); end; implementation var TrampolineBeginThread: function(SecurityAttributes: Pointer; StackSize: LongWord; ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord; var ThreadId: TThreadID): THandle = nil; threadvar StackSizeOverride: LongWord; function InterceptBeginThread(SecurityAttributes: Pointer; StackSize: LongWord; ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord; var ThreadId: TThreadID): THandle; const STACK_SIZE_PARAM_IS_A_RESERVATION = $00010000; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx begin if StackSizeOverride <> 0 then begin CreationFlags := CreationFlags or STACK_SIZE_PARAM_IS_A_RESERVATION; StackSize := StackSizeOverride; StackSizeOverride := 0; end; Result := TrampolineBeginThread(SecurityAttributes, StackSize, ThreadFunc, Parameter, CreationFlags, ThreadId); end; constructor TThreadHelper.Create(CreateSuspended: Boolean; StackSize: LongWord); begin StackSizeOverride := StackSize; inherited Create(CreateSuspended); end; initialization TrampolineBeginThread := InterceptCreate(@BeginThread, @InterceptBeginThread); finalization InterceptRemove(@TrampolineBeginThread, @InterceptBeginThread); end. 控制堆栈大小。出于任何原因,TThread的设计人员都未能在TThread的构造函数中包含堆栈大小参数。这显然是一个遗漏。您应该直接致电TThreadBeginThread

[如果您只是急于进行黑客工作,则需要找到CreateThread单元的实现部分中声明的ThreadProc函数的地址。一些可能的方法:

  1. 在运行时分解Classes以读出TThread.Create的地址。
  2. 创建一个虚拟线程,该虚拟线程查看其调用堆栈以查找ThreadProc的地址。
  3. 使用弯路勾住ThreadProc。创建一个虚拟线程。注意传递的线程过程的地址。那是BeginThread

ThreadProc的源代码是此类黑客的好方法。

[另一种应用骇客的方法将再次是绕行madExcept。然后,您可以使用线程局部变量来提供堆栈大小。该线程局部变量的BeginThread值表示“使用作为参数传递的值”,而其他任何值将是绕行的high(LongWord)使用的值。


3
投票

正如BeginThread指出的那样,您无法控制使用David类创建的线程的堆栈大小。您必须使用TThreadBeginThread自己创建实际的线程。

但是,如果您的应用程序中的每个线程不需要不同的堆栈大小:然后,您可以使用最小堆栈大小最大堆栈大小的链接选项设置默认堆栈大小。

要么在项目选项中设置选项,要么使用伪指令:CreateThread


2
投票

对于Delphi 10.3 RIO和更高版本,现在有一个重载的构造函数,使您可以在Windows平台上为TThread设置ReservedStackSize。

© www.soinside.com 2019 - 2024. All rights reserved.