(不好意思)怎样保证主程序退出时线程一定已关闭?

wyj 2000-01-03 11:42:00
我曾用WaitFor方法在主程序退出前等待各线程结束,效果比较好,但如果线程中使用了VCL的话,这个方法就会引起死锁,怎么办呢?
...全文
622 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lotusgranger 2001-02-25
  • 打赏
  • 举报
回复
线程的运行状态用barton方法简单可行,若线程正在运行,而想马上退出,也可调用API强制杀掉线程。
光明山人 2000-01-06
  • 打赏
  • 举报
回复
让小弟来说两句:

Delphi Help about TThread.Terminate;

The thread's Execute method and any methods that Execute calls should check Terminated periodically and exit when it's True.

我想在TYourThread的Execute中应该是这样的(至少间接):
while not Terminated do
begin
刷新程序
end;
在Execute运行完以后线程就结束了,当然我认为还是应当用Synchronize,原因很简单,就是因为它简单,不用再另外弄其它东东。

在你的主程序中还可以这样写:

退出之前:
while not myThread.Suspended/或者别的信号 do
Application.ProcessMessages;
tiger 2000-01-04
  • 打赏
  • 举报
回复
字面上是同步, Delphi里也是一个函数. ^_^
kxy 2000-01-04
  • 打赏
  • 举报
回复
"不用Synchronize,照样可以操纵VCL"是不用同步,写线程要考虑同步等问题,
当然,同步可以使用很多方法,临界区,信号量,互斥量,事件等.Synchronize指的
是同步,还是一个函数?
kxy 2000-01-04
  • 打赏
  • 举报
回复
以下是 delphi中help的一部分
Don't call WaitFor in the context of the main VCL thread if the thread uses Synchronize. Doing so will either cause a deadlock, making it appear that the application has hung, or raise an EThread exception.

Synchronize waits for the main VCL thread to enter the message loop before allowing the method it is trying to synchronize to execute. If the main VCL thread has called WaitFor, it won't enter the message loop and Synchronize will never return. TThread detects that case and will raise an EThread exception in the thread causing it to terminate and, if not caught in the Execute method, the application will terminate as well. If Synchronize is already waiting on the main VCL thread when WaitFor is called, TThread can't intervene, and the application will deadlock.
所有,如果线程中使用了 vcl,Synchronize一定不要使用waitfor.

保证主程序退出时线程一定已关闭,可能要根据具体情况.
把Thread的FreeOnTerimte := Ture;
FormClose 中Thread.Free; 等
可以贴一些代码吗?
tiger 2000-01-04
  • 打赏
  • 举报
回复
"不用Synchronize,照样可以操纵VCL"是对的
因为可以用临界区(TCriticalSection)同样能达到
Synchronize的目的
wyj 2000-01-04
  • 打赏
  • 举报
回复
回复KXY先生:对不起,我说的死锁是指由于线程中使用了Synchronize从而引起主程序永远无法进入消息循环而引起的整体死锁,正因为如此,如果线程中使用了Synchronize函数的话,在主程序中就不能使用WaitFor来等待线程结束,关键在这儿,十分感谢您的回答,但问题还是没有解决,希望您再次给予帮助,谢谢。
kxy 2000-01-04
  • 打赏
  • 举报
回复
>>>不用Synchronize,照样可以操纵VCL。
当然可以操作,但是不对,
例如:两个Thread同时对TStringList操作,一个修改的同时,如果不同步,
另一个同时把他的给删除了,怎么办?
>>>>因为所有的thread terminate都只是给thread发信号, 而不能保证thread是否结束
看看源码就知道,thread.termnate只是把一个变量设成True;
>>
可以看看delphi中的用Thread排序的例子,不过有问题。
可以看我提的问题有关TThread的FreeOnTerminte
http://www.midatech.com/csdn/expert/TopicView.asp?id=5
barton 2000-01-04
  • 打赏
  • 举报
回复
呵呵,Terminate方法并不能控制终止线程或者释放线程。这里也不涉及到线
程同步的问题,其实很简单:加一个控制变量,正常情况下,这个变量的值
是False,终止线程前将其设为True(由主线程完成),在线程中的每一个循环
中都监视这个变量,一旦变为True,马上Exit,线程自然终止了。在线程的
OnTerminate过程中加入一控制变量,线程开始时设为False,终止后设为True
(因为线程的实例可能已被释放,不能访问Terminated属性),只有这个变量
为True时才可以关闭窗口。
tiger 2000-01-04
  • 打赏
  • 举报
回复
我觉得以现在delphi封装的thread类用了synchronize, 根本不能完成wyj所要的功能. 因为所有的thread terminate都只是给thread发信号, 而不能保证thread是否结束
wyj1 2000-01-04
  • 打赏
  • 举报
回复
十分感谢各位大侠的无私帮助
kxy 2000-01-04
  • 打赏
  • 举报
回复
>>在主程序结束前当然要发一个Terminate命令
Terminate只是改变一个变量的值,并不是让Thread结束.
可以看看delphi中的用Thread排序的例子,在排序过程中退出程序,没有引起一个异常,
排序时在画布上画线,和你的程序很相似.
但是在排序过程中退出程序,有内存泄漏,此问题已经讨论过.
可以看我提的问题有关TThread的FreeOnTerminte
http://www.midatech.com/csdn/expert/TopicView.asp?id=5;
barton 2000-01-04
  • 打赏
  • 举报
回复
似乎不同的版本有所区别。我用D3写的代码运行没错,而在D5下运行线程就出
问题。不用Synchronize,照样可以操纵VCL。
TThreadProc = procedure of object;

TMyThread = class(TThread)
private
FThreadProc: TThraedProc;
protected
procedure Execute; override;
public
constructor Create(ActionProc: TThreadProc; TerminateProc: TNotifyEvent);
end;

...
implementation

procedure TMyThread.Execute;
begin
FThreadProc;
end;

constructor TMyThread.Create(ActionProc: TThreadProc; TerminateProc: TNotifyEvent);
begin
FreeOnTerminate := True;
FThreadProc := ActionProc;
OnTerminate := TerminateProc;
inherited Create(False);
end;

线程代码在ActionProc中,线程结束代码在TerminateProc中,两个代码均在
主线程环境下运行。主线程终止时必须等待从线程终止。

tiger 2000-01-04
  • 打赏
  • 举报
回复
试试看用try... except...end 把它封装掉
wyj 2000-01-04
  • 打赏
  • 举报
回复
本人十分感谢各位大侠:我比较菜也比较懒,不想考虑是否要使用Synchronize的问题,反正线程中已经用了,用了就用了吧。实际的模式是这样的,主窗口中有一个LISTBOX,线程不断地刷新它,在主程序结束前当然要发一个Terminate命令,但是如果此时线程尚未完全结束的话,它下一次刷新这个LISTBOX就会引起一个异常,因为此时主窗口已经释放了。为此我很头痛。
kxy 2000-01-03
  • 打赏
  • 举报
回复
VCL是非线程的,使用VCL相关的东东一定要使用 Synchronize.
具体可以看delphi 的 Help Using the main VCL thread

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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