向 CreateThread 传递参数

发布于 2024-10-19 00:43:20 字数 755 浏览 8 评论 0原文

我在调用 CreateThread 时将类引用作为参数传递给 ThreadProc 时遇到问题。这是一个示例程序,演示了我遇到的问题:

program test;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, Dialogs;

type
    TBlah = class
        public
        fe: Integer;
    end;

function ThreadProc(param: Pointer) : DWORD;
begin
    ShowMessage(IntToStr(TBlah(param).fe));

    Result := 0;
end;

var
    tID: DWORD;
    handle: THandle;
    b: TBlah;
begin
    b := TBlah.Create;
    b.fe := 54;

    handle := CreateThread(nil, 0, @ThreadProc, Pointer(b), 0, tID);

    WaitForSingleObject(handle, INFINITE); 
end.

ShowMessage 的调用会弹出一个消息框,其中包含类似 245729105 的内容,而不是 54< /code> 正如我所料。

这可能只是对 Delphi 工作原理的一个基本误解,所以有人可以告诉我如何让它正常工作吗?

I am having a problem passing a class reference as the parameter to the ThreadProc in a call to CreateThread. Here is a sample program that demonstrates the problem I am having:

program test;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, Dialogs;

type
    TBlah = class
        public
        fe: Integer;
    end;

function ThreadProc(param: Pointer) : DWORD;
begin
    ShowMessage(IntToStr(TBlah(param).fe));

    Result := 0;
end;

var
    tID: DWORD;
    handle: THandle;
    b: TBlah;
begin
    b := TBlah.Create;
    b.fe := 54;

    handle := CreateThread(nil, 0, @ThreadProc, Pointer(b), 0, tID);

    WaitForSingleObject(handle, INFINITE); 
end.

The call to ShowMessage pops up a message box that has something like 245729105 in it, not 54 like I expect.

This is probably just a basic misunderstanding of how Delphi works, so could someone please tell me how to get this working properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧瑾黎汐 2024-10-26 00:43:20

这里的问题是你的线程函数有错误的调用约定。您需要使用 stdcall 约定来声明它:

function ThreadProc(param: Pointer) : DWORD; stdcall;

在此处输入图像描述


话虽如此,它更惯用的做法是使用 TThread 后代来为您处理 OOP 到 C 函数返回 OOP 的转换。看起来像这样:

type
  TBlah = class(TThread)
  protected
    procedure Execute; override;
  public
    fe: Integer;
  end;

procedure TBlah.Execute;
begin
  ShowMessage(IntToStr(fe));
end;

var
  b: TBlah;

begin
  b := TBlah.Create(True);
  b.fe := 42;
  b.Start;
  b.WaitFor;
end.

顺便说一句,有人知道为什么 Windows.pas 将 TFNThreadStartRoutine 声明为 TFarProc 而不是正确类型化的函数指针吗?

The problem here is that your thread function has the wrong calling convention. You need to declare it with the stdcall convention:

function ThreadProc(param: Pointer) : DWORD; stdcall;

enter image description here


Having said that, it would be more idiomatic to just use a TThread descendant which handles the OOP to C function back to OOP transitioning for you. That would look like this:

type
  TBlah = class(TThread)
  protected
    procedure Execute; override;
  public
    fe: Integer;
  end;

procedure TBlah.Execute;
begin
  ShowMessage(IntToStr(fe));
end;

var
  b: TBlah;

begin
  b := TBlah.Create(True);
  b.fe := 42;
  b.Start;
  b.WaitFor;
end.

Incidentally, does anyone know why Windows.pas declares TFNThreadStartRoutine as TFarProc rather than a proper typed function pointer?

只是一片海 2024-10-26 00:43:20

您忘记了 stdcall 指令。

function ThreadProc(param: Pointer) : DWORD; stdcall;

You're forgetting the stdcall directive.

function ThreadProc(param: Pointer) : DWORD; stdcall;
夏日浅笑〃 2024-10-26 00:43:20

并且不要使用 Pointer 转换:

handle := CreateThread(nil, 0, @ThreadProc, **Pointer**(b), 0, tID); 

b 已经是一个 Pointer (一个 Class,它是一个 <代码>对象 <代码>指针)

And don't use Pointer cast in:

handle := CreateThread(nil, 0, @ThreadProc, **Pointer**(b), 0, tID); 

b is already a Pointer (a Class, which is an Object Pointer)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文