线程结束后的奇怪问题! ( 积分: 100 )

  • 主题发起人 主题发起人 yitang
  • 开始时间 开始时间
Y

yitang

Unregistered / Unconfirmed
GUEST, unregistred user!
写了个简单的线程作测试,但碰到了一些不解的问题
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,bytearray, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
Function getthreadcount():word;
private
{ Private declarations }
procedure threaddestroy(Sender:Tobject);
public
{ Public declarations }
end;

var
Form1: TForm1;
ThreadCount:word;

implementation
uses unit2;
{$R *.dfm}
procedure Tform1.threaddestroy(Sender:Tobject);
begin
inc(Threadcount,-1);
//showmessage(inttostr(ThreadCount));这里的ThreadCount值的确会递减
end;

function TForm1.getthreadcount():word;
begin
result:=threadcount;
end ;
procedure TForm1.Button1Click(Sender: TObject);
var
n:word;
begin
ThreadCount:=5;//这里简化了,只是想说明最终会创建5个线程
for n:=1 to 5do
begin
with mythread.create(n)do
//线程已经inherited create(false),FreeonTerminate:=true
onterminate:=threaddestroy;
end;
sleep(10000);//确保所有线程都有足够时间完成! 线程定义很简单!
showmessage(inttostr(getthreadcount));//问题:这里显示的是5
showmessage(inttostr(getthreadcount));// 这里显示的是0;
end;

end.

大家帮看一下,我想了一个下午也没有找出原因!谢谢!
 
写了个简单的线程作测试,但碰到了一些不解的问题
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,bytearray, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
Function getthreadcount():word;
private
{ Private declarations }
procedure threaddestroy(Sender:Tobject);
public
{ Public declarations }
end;

var
Form1: TForm1;
ThreadCount:word;

implementation
uses unit2;
{$R *.dfm}
procedure Tform1.threaddestroy(Sender:Tobject);
begin
inc(Threadcount,-1);
//showmessage(inttostr(ThreadCount));这里的ThreadCount值的确会递减
end;

function TForm1.getthreadcount():word;
begin
result:=threadcount;
end ;
procedure TForm1.Button1Click(Sender: TObject);
var
n:word;
begin
ThreadCount:=5;//这里简化了,只是想说明最终会创建5个线程
for n:=1 to 5do
begin
with mythread.create(n)do
//线程已经inherited create(false),FreeonTerminate:=true
onterminate:=threaddestroy;
end;
sleep(10000);//确保所有线程都有足够时间完成! 线程定义很简单!
showmessage(inttostr(getthreadcount));//问题:这里显示的是5
showmessage(inttostr(getthreadcount));// 这里显示的是0;
end;

end.

大家帮看一下,我想了一个下午也没有找出原因!谢谢!
 
线程跟主线程在第一次showmessage时没同步,所以是5,第二次同步了,所以是0
你那个线程创建后就自己释放了,所以得到是0了
 
在线程体ThreadProc中,线程任务执行完毕结束前调用了DoTerminate,
procedure TThread.DoTerminate;
begin
if Assigned(FOnTerminate) then
Synchronize(CallOnTerminate);
end;
procedure TThread.CallOnTerminate;
begin
if Assigned(FOnTerminate) then
FOnTerminate(Self);
end;
这说明OnTerminate事件是同步调用的,实际在主线程中执行的。而Synchronize同步调用的实现是通过向主线程发送一个WM_NULL消息唤醒主线程然后通知它调用CheckSynchronize来执行同步过程的。
procedure TApplication.WndProc(var Message: TMessage);
begin
...
WM_NULL:
CheckSynchronize;
...
end;

sleep(10000);//确保所有线程都有足够时间完成! 线程定义很简单!
showmessage(inttostr(getthreadcount));//问题:这里显示的是5
showmessage(inttostr(getthreadcount));// 这里显示的是0;
你在创建线程之后,主线程就Sleep转移控制权10秒,这期间它不处理任何消息,因此这时尽管线程都执行完了,但OnTerminate事件却不能马上执行,线程还在等着主线程同步调用呢,getthreadcount自然是5,而第一次ShowMessage后,主线程ShowModal出一个消息框后,它就又开始了消息循环,这样就会处理调用同步过程,下次ShowMessage是显示结果自然就是0啦
function TCustomForm.ShowModal: Integer;
begin
...
repeat
Application.HandleMessage;
if Application.FTerminate then
ModalResult := mrCancel else
if ModalResult <> 0 then
CloseModal;
until ModalResult <> 0;
...
end;
 

Similar threads

回复
3
查看
362
迷惘的人
Q
回复
4
查看
370
穿越沦陷的爱
穿
L
回复
9
查看
301
lcl_003
L
后退
顶部