2017-04-05 115 views
2

如果在Delphi XE3中使用BeginThread,函数被阻塞。这是为什么?BeginThread delphi阻塞函数

我试图在下面创建我的问题的最小版本。如果按下了2个按钮,如果按下按钮btn1,则btn1的标题应该变为'nooo'。如果btn2被按下btn1标题改为'yesss'。

当按下btn1时,我还使用BeginThread启动一个线程,该线程永远循环。

问题在于,btn1.Caption:='nooo';从BeginThread块开始永远不会被释放。我得到btn1.Caption:='nooo';

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    btn1: TButton; 
    btn2: TButton; 
    procedure btn1Click(Sender: TObject); 
    procedure btn2Click(Sender: TObject); 

    private 
    function test() : Integer; 
    { Private declarations } 
    public 

    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

function TForm1.test() : Integer; 
begin 

    while True do 
    begin 
     Sleep(Random(1000) * 2); 
    end; 
    Result := 0; 
end; 

procedure TForm1.btn1Click(Sender: TObject); 
var 
    id: LongWord; 
begin 
    BeginThread(nil, 0, Pointer(test), nil, 0, id); 
    btn1.Caption := 'nooo'; 
end; 

procedure TForm1.btn2Click(Sender: TObject); 
begin 
    btn1.Caption := 'yesss'; 
end; 

end. 
+0

使用的TThread类,而不是和不'吨浪费你的时间! –

+0

你的演员在于编译器,你付出代价。 –

+0

调试提示:在'BeginThread'行放置一个断点。当你到达断点时,按'F7'键进入该方法。您将直接进入“测试”方法,这应该是解决问题的线索。 –

回答

7

表达Pointer(test)呼叫test()然后键入-连铸结果到Pointer。由于test()永远不会返回,因此无法投射结果,因此没有值传递给BeginThread()BeginThread()本身不会阻塞;它永远不会被首先调用。

BeginThread()的第三个参数不是Pointer类型;它是TThreadFunc类型,它是一个独立(非成员)函数,它接收一个Pointer参数并返回Integer。您的TForm1.test()方法不符合条件,因为它不是独立功能。

test()是一个独立的功能,然后直接把它传递给BeginThread()(没有任何类型的铸造或@运营商):

function test(param: Pointer): Integer; 
begin 
    while True do 
    Sleep(Random(1000) * 2); 
    Result := 0; 
end; 

var 
    id: LongWord; 
begin 
    BeginThread(nil, 0, test, nil, 0, id); 
end; 
+2

否则,请使用'TThread'类,它在内部使用'BeginThread()'。 –