delphi 如何在自动终止线程和手动终止线程时都正确的设置窗体上的控件 10
delphi中释放线程有两种方法,自动释放和手动释放。1、自动释放:将FreeOnTerminate属性设置为True,Execute方法执行完后会自动执行析构函数。2、...
delphi中释放线程有两种方法,自动释放和手动释放。
1、自动释放:将FreeOnTerminate属性设置为True,Execute方法执行完后会自动执行析构函数。
2、手动释放:
我是这样处理的:
thread.Terminate;
thread.WaitFor;
thread.Free;
释放前必须调用WaitFor方法等待线程执行完后,否则Free的时候可能因为线程还未执行完报错。
我的界面上有两个按钮,启动和停止,点击启动按钮启动线程,启动按钮置灰,停止按钮可用。当线程执行完后需要将启动按钮置为可用,停止按钮置灰。
启动按钮.Enabled := True;
停止按钮.Enabled := False;
这两句我是在线程的Destroy方法是执行的。
如果FreeOnTerminate设置为True,线程自动释放,线程执行完后没有问题。
但我在界面上点击停止按钮的时候,需要手动去终止并释放线程,必须调用WaitFor等线程执行完后才能释放,而这个方法不允许FreeOnTerminate属性设置为True。
我该如何处理线程,使之自己执行完或手动终止它都能正确的设置两个按钮的Enabled状态呢?
同事给我的建议是,FreeOnTerminate属性设置为True,执行完后自动释放。点击停止时给一个自定义属性Stop设置为True(在Execute方法中判断如果Stop为True,则Exit),而
不调用Terminate方法。这样当Execute执行时判断Stop属性为True,结束执行方法,自动释放。基本上可以解决我的问题。但是如果我关闭窗体,这时也需要将Stop设置为True终
止线程,但将该属性设置为True,线程可能不会马上执行完(因为线程执行调用的方法是一个递归方法),这个时候线程未执行完而窗体释放会提示地址错误。
各位有什么更好的办法吗?让一个线程不管是自动终止还是手动终止都能正确的设置这两个按钮的状态。 展开
1、自动释放:将FreeOnTerminate属性设置为True,Execute方法执行完后会自动执行析构函数。
2、手动释放:
我是这样处理的:
thread.Terminate;
thread.WaitFor;
thread.Free;
释放前必须调用WaitFor方法等待线程执行完后,否则Free的时候可能因为线程还未执行完报错。
我的界面上有两个按钮,启动和停止,点击启动按钮启动线程,启动按钮置灰,停止按钮可用。当线程执行完后需要将启动按钮置为可用,停止按钮置灰。
启动按钮.Enabled := True;
停止按钮.Enabled := False;
这两句我是在线程的Destroy方法是执行的。
如果FreeOnTerminate设置为True,线程自动释放,线程执行完后没有问题。
但我在界面上点击停止按钮的时候,需要手动去终止并释放线程,必须调用WaitFor等线程执行完后才能释放,而这个方法不允许FreeOnTerminate属性设置为True。
我该如何处理线程,使之自己执行完或手动终止它都能正确的设置两个按钮的Enabled状态呢?
同事给我的建议是,FreeOnTerminate属性设置为True,执行完后自动释放。点击停止时给一个自定义属性Stop设置为True(在Execute方法中判断如果Stop为True,则Exit),而
不调用Terminate方法。这样当Execute执行时判断Stop属性为True,结束执行方法,自动释放。基本上可以解决我的问题。但是如果我关闭窗体,这时也需要将Stop设置为True终
止线程,但将该属性设置为True,线程可能不会马上执行完(因为线程执行调用的方法是一个递归方法),这个时候线程未执行完而窗体释放会提示地址错误。
各位有什么更好的办法吗?让一个线程不管是自动终止还是手动终止都能正确的设置这两个按钮的状态。 展开
3个回答
展开全部
在Delphi中使用线程,当窗体关闭时,如果窗体中启用了线程,一般需要手动关闭,以释放资源。 常用来结束线程的代码为:
thread.Terminate;
thread.WaitFor;
即先触发Terminate方法,然后等待线程的结束。这种方法要求线程不能使用
FreeOnTerminate := True;
否则在WaitFor即将结束的时候会引发“无效句柄”的错误。 这种方法在窗体关闭的时候会等待一段事件(因为WaitFor)。
因此,如果不是在主窗体中结束线程时,其实我们可以不必使用WaitFor。而是采用如下方法: 将FreeOnTerminate := True;这样在窗体关闭的代码中直接调用
thread.Terminate; 即可。
注意: 如果设置了 thread.OnTerminate := SomeFunction; 那么在调用PcmThrd.Terminate;前尽量将thread.OnTerminate := nil,以免结束线程后SomeFunction中的变量出现空指针错误。当然,这不是绝对的,需要根据具体程序而定 .
thread.Terminate;
thread.WaitFor;
即先触发Terminate方法,然后等待线程的结束。这种方法要求线程不能使用
FreeOnTerminate := True;
否则在WaitFor即将结束的时候会引发“无效句柄”的错误。 这种方法在窗体关闭的时候会等待一段事件(因为WaitFor)。
因此,如果不是在主窗体中结束线程时,其实我们可以不必使用WaitFor。而是采用如下方法: 将FreeOnTerminate := True;这样在窗体关闭的代码中直接调用
thread.Terminate; 即可。
注意: 如果设置了 thread.OnTerminate := SomeFunction; 那么在调用PcmThrd.Terminate;前尽量将thread.OnTerminate := nil,以免结束线程后SomeFunction中的变量出现空指针错误。当然,这不是绝对的,需要根据具体程序而定 .
追问
确实,线程不是在主窗体上定义的,是在MDI子窗体上定义的,按照你的做法,我在窗体的析构函数(不是Close事件中)中执行thread.Terminate方法,仍报内存地址错误。
运行期在创建的对象按理说应该手动释放的,窗体释放了,那么窗体上的对象也应该释放了,为什么还会报内存地址错误呢?
追答
那只能看你的源代码了.需要分析一下.才知道.
展开全部
手动时,FreeOnTerminate 也设置为true
启动按钮.Enabled := True;
停止按钮.Enabled := False;
这2句不放在destroy里,放在execute方法的最后面执行,应该可以.
启动按钮.Enabled := True;
停止按钮.Enabled := False;
这2句不放在destroy里,放在execute方法的最后面执行,应该可以.
追问
如果设置了FreeOnTerminate为True,execute执行完后会自动执行析构函数,放在execute最后和Destroy里不是一样吗?如果使用者不点击停止,而是直接关闭窗体,这时我也要在窗体的关闭事件中执行thread.Terminate方法,但执行这个方法线程可能不会马上就停止,而这时窗体却执行了释放,也就是窗体释放时,线程还未执行完,不就会有内存泄露了吗?
追答
那你在线程里判读下,窗体是否已经不存在了nil.不存在就不要再刷新窗体了.
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
感觉是你的线程没写好,不然的话不会出现这种情况。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询