多线程编程(2) – 一切从 CreateThread 开始

产生一个线程

产生一个线程,是以 CreateThread() 作为一切行动的开始。此函数的原型如下:

function CreateThread(
  lpThreadAttributes: Pointer;  // 安全设置,nil 表示缺省值
  dwStackSize: SIZE_T;  // 堆栈大小,0 表示缺省大小
  lpStartAddress: TFNThreadStartRoutine; // 入口函数,新线程开始的地址,函数指针
  lpParameter: Pointer;   // 函数参数,传递到上面的函数去
  dwCreationFlags: DWORD;                // 启动选项,默认是立即开始执行
  var lpThreadId: DWORD                  // 新线程的 ID 将会传回这里
): THandle; stdcall;                     // 返回值,如果成功返回一个 handle,代表新线程

TThread.Create 先调用了 BeginThread,如下代码片段:

{$IF Defined(MSWINDOWS)}
constructor TThread.Create(CreateSuspended: Boolean; ReservedStackSize: NativeUInt);
begin
  inherited Create;
  FSuspended := not FExternalThread;
  FCreateSuspended := CreateSuspended and not FExternalThread;
  if not FExternalThread then
  begin
    if ReservedStackSize <> 0 then
      FHandle := BeginThread(nil, ReservedStackSize, @ThreadProc, Pointer(Self), CREATE_SUSPENDED or STACK_SIZE_PARAM_IS_A_RESERVATION, FThreadID)
    else
      FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
    if FHandle = 0 then
      raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
  end else
  begin
    FHandle := Winapi.Windows.GetCurrentThread;
    FThreadId := GetCurrentThreadId;
  end;
end;

BeginThread 又调用了 CreateThread,如下代码节选:

{$IFDEF MSWINDOWS}
function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
  ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
  var ThreadId: TThreadID): THandle;
var
  P: PThreadRec;
begin
  if Assigned(SystemThreadFuncProc) then
    P := PThreadRec(SystemThreadFuncProc(ThreadFunc, Parameter))
  else
  begin
    New(P);
    P.Func := ThreadFunc;
    P.Parameter := Parameter;
  end;

  IsMultiThread := TRUE;

  Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
    CreationFlags, ThreadID);

  { P variable is supposed to be freed by the ThreadWrapper routine.
    If the call to CreateThread fails, then ThreadWrapper will not be called
    and P will not get freed. Check for failure now and free P if required.
  }
  if Result = 0 then
    Dispose(P);
end;

结束一个线程

可以靠线程函数的结束而结束线程,有时候还需要更强制的手法结束一个线程,使用 ExitThread()

procedure ExitThread(dwExitCode: DWORD); stdcall;

只有一个 dwExitCode 参数,指定此线程的结束代码。

posted on 2022-03-05 10:38  pchmonster  阅读(275)  评论(0编辑  收藏  举报

导航