将参数传递给CreateThread函数

3

我遇到了一个问题,即在调用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

这可能只是对Delphi工作原理的基本误解,所以请问有人可以告诉我如何使其正常工作吗?

3个回答

10

问题在于你的线程函数调用约定错误。你需要使用stdcall约定声明它:

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

enter image description here


话虽如此,更符合惯用语的做法是使用一个TThread的派生类,它会为您处理OOP到C函数的转换。代码如下:

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而不是一个正确的类型化函数指针吗?


3
b.fe := 42;,别忘了冒号 :) - Kokonotsu
2
@Kokonotsu 不使用 TThread 有什么特别的原因吗?至于 = vs :=,我猜我今天做了太多的 P/Invoke! - David Heffernan
很多打字,還有一個截圖... 你真快! - Sertac Akyuz
@David:知道一下,我从来没有见过332分的人:http://stackoverflow.com/tags/delphi/topusers。 - Andreas Rejbrand
@Andreas 我更多地考虑这个:http://stackexchange.com/leagues/1/week/stackoverflow - David Heffernan
显示剩余2条评论

9
你忘记了 stdcall 指令。
function ThreadProc(param: Pointer) : DWORD; stdcall;

1

不要在以下情况下使用指针转换:

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

b 已经是一个 指针(一个,它是一个对象指针


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接