2016-03-18 32 views
1

我正在制作一个单元,在该单元中我用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 

正如我解决这个问题?

+1

你的意思是“投掷”在“发射”?我只是问,因为“throw”通常用于“抛出异常”的意义上...... – MartynA

+0

在本机中使用BeginThread启动函数线程 – asdzxc

+0

如果您的意思是*启动线程*,请写*启动线程* 。如果你说出你的意思,它会让你更容易理解你的问题。 :-) –

回答

4

您不能使用非静态类方法作为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. 
+0

访问冲突也可能来自将'PDWORD(0)^'作为'var'参数传递给threadId。该方法需要一个有效的地址来写入线程ID值。当然,这并不是说你所说的一切都不正确。如果没有'self'参数,访问实例变量'probando'的尝试也会导致AV。 –

+1

@J ...:在Windows上,'BeginThread()'是Win32'CreateThread()'函数的一个封装,如果调用者不需要线程ID,它允许该特定参数为NULL。 –

+0

我站好了。我在调用'BeginThread'时总是使用ThreadID参数,所以对我来说这似乎很奇怪,但MSDN同意它可以为NULL。 –