我正在制作一个单元,在该单元中,我使用BeginThread以及在类中定义的变量来引发线程。

码:

unit practica;

interface

uses Windows;

type
  TTest = class
  private
  public
    probando: integer;
    procedure iniciar_thread;
    procedure load_now;
  end;

implementation

procedure TTest.load_now;
begin
  Sleep(probando);
end;

procedure TTest.iniciar_thread;
begin
  BeginThread(nil, 0, @TTest.load_now, nil, 0, PDWORD(0)^);
end;

end.


形式:

procedure TForm1.testClick(Sender: TObject);
  test:TTest;
begin
  test := TTest.Create();
  test.probando := 1000;
  test.iniciar_thread;
end;


编译时没有错误,但是当您运行函数时,我得到以下信息:

Exception EAccessViolation in module test.exe
    System Error. Code5
    Runtime error 217


当我解决这个问题?

最佳答案

您不能将非静态类方法用作BeginThread()的线程过程。查看BeginThread()的声明:

type
  TThreadFunc = function(Parameter: Pointer): Integer;

function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
  ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
  var ThreadId: TThreadID): Integer;


如您所见,它期望一个独立的函数,而不是一个类方法。即使这样做,您的类方法甚至也没有正确的签名。

尝试类似这样的方法:

unit practica;

interface

type
  TTest = class
  private
    FThread: Integer;
  public
    probando: integer;
    procedure iniciar_thread;
    procedure load_now;
  end;

implementation

uses
  Windows;

procedure TTest.load_now;
begin
  Sleep(probando);
end;

function MyThreadFunc(Parameter: Pointer): Integer;
begin
  TTest(Parameter).load_now;
end;

procedure TTest.iniciar_thread;
var
  ThreadId: TThreadID;
begin
  FThread := BeginThread(nil, 0, MyThreadFunc, Self, 0, ThreadId);
end;

end.


使用完所有内容后,别忘了终止线程,由CloseHandle()返回的线程句柄BeginThread()Free()您的TTest对象。

通常,您不应该直接使用BeginThread()。您应该改为从TThread派生一个类:

unit practica;

interface

type
  TTest = class
  public
    probando: integer;
    procedure iniciar_thread;
  end;

implementation

uses
  Classes, Windows;

type
  TMyThread = class(TThread)
  private
    FTest: TTest;
  protected
    procedure Execute; override;
  public
    constructor Create(ATest: TTest);
  end;

constructor TMyThread.Create(ATest: TTest);
begin
  inherited Create(False);
  FreeOnTerminate := True;
  FTest := ATest;
end;

procedure TMyThread.Execute;
begin
  Sleep(FTest.probando);
end;

procedure TTest.iniciar_thread;
begin
  TMyThread.Create(Self);
end;

end.

10-08 04:48