还是一个关于线程的问题,不明白

看那山瞧那水 2011-09-22 04:18:04
瞧代码:


unit unMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
unThread;

type
TfrmMain = class(TForm)
btn1: TButton;
btn2: TButton;
lbl1: TLabel;
lbl2: TLabel;
lbl3: TLabel;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
private
{ Private declarations }
myThread:TMyThread;

public
{ Public declarations }

end;

var
frmMain: TfrmMain;
EndThread:Boolean;

implementation

{$R *.dfm}

procedure TfrmMain.btn1Click(Sender: TObject);
begin
EndThread:=False;
myThread:=TMyThread.Create(False);

end;

procedure TfrmMain.btn2Click(Sender: TObject);
var
rv:DWORD;
wv:Integer;
i:Integer;
begin
rv:=5;

myThread.Terminate;

Application.ProcessMessages; //就是这里了,一定要加这句,下面的一句WaitForSingleObject()才有效,才不会超时! 如果不加,都是超时的(当然是线程还没有执行完,要Terminate中断的情况下)

rv:=WaitForSingleObject(myThread.Handle,5000);

case rv of
WAIT_ABANDONED: lbl3.Caption:='中断了';
WAIT_OBJECT_0: lbl3.Caption:='正常结束';
WAIT_TIMEOUT : lbl3.Caption:='超时';
5:lbl3.Caption:='55555';
end;

end;

end.


unit unThread;

interface

uses
Windows, Classes;

type
TMyThread = class(TThread)
private
{ Private declarations }
procedure OnMyThreadTerminate(Sender:TObject);
protected
procedure Execute; override;
end;

implementation

uses unMain;

{ TMyThread }

procedure TMyThread.Execute;
var
i,j:Integer;
k:Double;
begin
OnTerminate:=OnMyThreadTerminate;
//FreeOnTerminate:=True; //这个设置了,就不能用WaitForSingleObject()函数了,因为句柄被释放了,我估计


for i:=0 to 2000000 do
begin

if Terminated then
Break;
for j:=0 to 2000 do
begin

if Terminated then
Break;
k:=(i+1) / Sqrt(Sqr((j+5)/5)+16);
end;
end;

end;

procedure TMyThread.OnMyThreadTerminate(Sender: TObject);
begin
frmMain.lbl1.Caption:='Thread Terminate';
end;

end.

如果不加Application.ProcessMessages;这句代码,也可以在别的地方设置myThread.Terminate;比如在另一个按钮点击事件里也行。

有人能解释下这个事吗?

有时想结束一个线程,设置了Terminate=true,不一定马上结束,所以想用WaitForSingleObject()来判断,线程运行时是无信号状态,结束了是有信号状态。

也看了看<<windows核心编程>>相关章节,都是用API实现的。
...全文
134 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZyxIp 2011-09-22
  • 打赏
  • 举报
回复
begin
//
end;
这种代码应该没有关系吧,编译器应该可以优化掉,你测试一下.
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zyxip 的回复:]

发完才看到,我和七楼的想的一样。
[/Quote]
还是你解释的清楚,我当时想的不是很全。
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
杯具的是,我在线程单元里留下这样的代码:

procedure TMyThread.OnMyThreadTerminate(Sender: TObject);
begin
//
end;

看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
2位大侠,就是你们说的情况了!!!
这个"OnTerminate在主线程里执行",误导我了。。。
把这个OnTerminate去了就OK了。
ZyxIp 2011-09-22
  • 打赏
  • 举报
回复
线程使用的基本原则就是不要在线程中去操作主线程的界面控件,这些控件都不是线程安全的.
最好是用PostMessage消息的方式。象OnTerminate 这种方法线程的源码是
procedure TThread.DoTerminate;
begin
if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;

它会去主线程中执行,所以这时主线程决不能阻塞了,否则子线程肯定也阻塞了.
ZyxIp 2011-09-22
  • 打赏
  • 举报
回复
发完才看到,我和七楼的想的一样。
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
粗步想法,是不是和消息队列和循环机制有关啊,因为是插入Application.ProcessMessages;这个是最顶层的消息处理环节了
ZyxIp 2011-09-22
  • 打赏
  • 举报
回复
线程的 OnTerminate 是要和主线程进行同步的。而这时主线程因为 WaitForSingleObject 而阻塞了。
所以只能等到 WaitForSingleObject 超时结束线程才能执行完 OnTerminate .
Application.ProcessMessages 造成的不超时只是假象,Application.ProcessMessages执行后,主线程响应了你的frmMain.lbl1.Caption:='Thread Terminate';方法,将这行代码执行完成了,这时线程真正结束了,你看到没有超时。
你在你 procedure TMyThread.Execute;的代码最后加一个 windows.Beep(1000,300);就算你有Application.ProcessMessages肯定还是超时。因为在执行Application.ProcessMessages后线程又执行了100毫秒,这里系统又早将执行权利交给了线程,又阻塞了。

没有 windows.Beep(1000,300);的时候,系统利用Application.ProcessMessages切换线程执行完成了OnTerminate 方法,然后才到了WaitForSingleObject 这句,所以看着好象没有超时。

如果要用WaitForSingleObject 等,就不要执行OnTerminate方法。


看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 m617105 的回复:]

其次少说了一点waitforsingleobject会让主线程直接进入休息状态,也就不会处理你操作界面控件
[/Quote]

是这样的,但是如果我在主线程里发出了myThread.Terminate;命令,然后再waitforsingleobject(),这个等待时间是很少的(百微秒级的),倒是不用关心界面操作的问题了。。。

比如我这样写:
myThread.Terminate;
Sleep(2000);
WaitForSingleObject(myThread.Handle,10000);

这个WaitForSingleObject还是报超时的
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jankercsdn 的回复:]

引用 7 楼 m617105 的回复:

个人估计可能跟下面这句有关系
OnTerminate:=OnMyThreadTerminate;
OnTerminate帮助上的解释
Occurs after the thread's Execute method has returned and before the thread is destroyed。
OnTerminate去执行操……
[/Quote]
呵呵,
回家研究研究
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
其次少说了一点waitforsingleobject会让主线程直接进入休息状态,也就不会处理你操作界面控件
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 m617105 的回复:]

个人估计可能跟下面这句有关系
OnTerminate:=OnMyThreadTerminate;
OnTerminate帮助上的解释
Occurs after the thread's Execute method has returned and before the thread is destroyed。
OnTerminate去执行操作主线程上的控件去了
而ProcessMes……
[/Quote]

呵呵。。。
应当不是这个原因,OnTerminate事件是在主线程执行的,不是在本线程执行,所以不用放在Synchronize里执行了,还有不分配这个事件,情况也是如此
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
个人估计可能跟下面这句有关系
OnTerminate:=OnMyThreadTerminate;
OnTerminate帮助上的解释
Occurs after the thread's Execute method has returned and before the thread is destroyed。
OnTerminate去执行操作主线程上的控件去了
而ProcessMessages则是要求理解处理队列中的要求,如果没有ProcessMessages可能就会过一会才会处理界面上的控件。
PS:如果说的不对,坐等高手指点
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
我实际中用的线程Execute()的代码大概是这样的:

while not Terminate do
begin
WaitForSingleObject(theEvent,INFINITE);//theEvent是同步事件

//任务
end;
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
to:m617105

置顶贴有吗?置顶贴关于线程运用的方式感觉好繁琐。我实际中用的线程还用不到贴子里说的那种方法。
我现在要关心的是我贴子里那句Application.ProcessMessages;
这句代码如果去掉了,就是超时的,我只是想知道为什么?
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
类似于这样的:
if Terminated then
Break;
换成
if WaitForSingleObject(ExitEvent,0)=WAIT_OBJECT_0 then
break;

线程类中添加
ExitEvent:TEvent;

procedure Stop();
begin
QuitEvent.SetEvent;
end;
主线程调用:
myThread.Terminate;
换成
myThread.Stop;
浩南_哥 2011-09-22
  • 打赏
  • 举报
回复
看那山瞧那水 2011-09-22
  • 打赏
  • 举报
回复
To:ZyxIp

谢谢你的回答,我关心的不是这个,你看我标识的红字。
我关心的是线程释放的时候,是要知道线程什么时候真正结束了,设置了Terminate,线程不一定就结束了,可能还在运行中。
因为某些原因,有些步骤要等线程结束了才能继续下去,所以用WaitForSingleObject来判断线程真正结束情况(当然可以有其它方法来判断,不过用WaitForSingleObject感觉比较直观).
呵呵,欢迎大家继续指教
ZyxIp 2011-09-22
  • 打赏
  • 举报
回复
最好用消息的方式,在
procedure TMyThread.Execute;
begin
//执行任务
PostMessage(窗体的Handle,自己的消息,0,0);
end;


窗体在收到消息后在进行其它的工作。

如果你非要同步等待,那你可以先将 线程的 Handle 保存起来放在一个变量中,不要总是用MyThread.handle.
这样就算是是MyThread释放了也没有关系。

在就是使用一个临界区,线程开始运行时进入,线程结束时关闭临界区。
在停止线程时先 调用 Terminate,然后下面的代码就是进入临界区,如果线程还没有结束,主线程就会等。

最好用消息的方式,这样不会将让主线程假死。


16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧