Correct thread terminate and destroy
http://www.techques.com/question/1-3788743/Correct-thread-destroy
Hello At my form I create TFrame at runtime.
At this frame I create background thread with executes commands in endless loop.
But when I destroy this frame I should destroy this thread. I try
thread.Suspend;
thread.Terminate;
FreeAndNil(thread);
but get AV and ThreadError. How should i destroy thread?
Don't suspend the thread. The terminate method just set the Terminated property to true,
and your Execute method is responsible to terminate the thread.
If it is suspended, it will not get a chance to terminate.
Another problem with the code above, is that it likely frees the thread
before it has a change to terminate the normal way.
You must make sure that thread exits it's execute method to terminate it properly.
Code could be something like this:
procedure TThread.Execute;
begin
while not Self.Terminated do
begin
//do something
end;
end;
Call this when You want to destroy thread:
thread.Terminate;
thread.WaitFor;
FreeAndNil(thread);
It's not necessary to call `Terminate` and `WaitFor` from the outside,
as the thread destructor will do it itself.
It may be necessary though to call it from overwritten destructors,
before any fields are freed, to make sure these are no longer used from the thread.
It is sufficient to do thread.Terminate.
But you will probably want to set thread.FreeOnTerminate := true when it is created.
Of course, in the tight loop of your thread (that is, in Execute),
you need to check if the thread has been requested to terminate
(check the Terminated property).
If you find that the thread has been requested to terminate,
simply break from the loop and exit from Execute.
thread.Terminate only sets FTerminated property to True. It doesn't destroy thread.
I know. But every thread must check for that in its Execute method.
I assume the OP is doing this.
You should never call suspend on a tthread its not safe to do so and resume should only be used to start a thread that was created suspended.
In Delphi 2010 the suspend and resume where depreciated and the method start was introduced to reinforce this.
For a more complete explanation see this thread at Codegears forums.
having said that there are 2 ways I will terminate and free a tthread.
1: I Set FreeOnTerminate when the thread is created so I just call.
Thread.Terminate;
2: Free the thread explicitly, as I need to read a result from a public property before the thread is freed and after it has terminated.
Thread.Terminate;
Thread.WaitFor;
//Do somthing like read a public property from thread object
if Thread <> nil then FreeAndNil(Thread);
In the main execute loop it may be a good idea to put some exception handling in.
Or you may be left wondering why the thread appears to terminate its self.
This may be causing the AV if the thread is set to FreeOnTerminate and it has already been freed when you try to free it.
procedure TThread.Execute;
begin
while not Terminated do
begin
try
//do something
except
on E:Exception do
//handle the exception
end;
end;
end;
Free a TThread either automatically or manually
I have a main thread and a separate thread in my program.
If the separate thread finishes before the main thread, it should free itself automatically.
If the main thread finishes first, it should free the separate thread.
I know about FreeOnTerminate, and I've read that you have to be careful using it.
My question is, is the following code correct?
procedure TMyThread.Execute;
begin
... Do some processing Synchronize(ThreadFinished); if Terminated then exit; FreeOnTerminate := true;
end; procedure TMyThread.ThreadFinished;
begin
MainForm.MyThreadReady := true;
end; procedure TMainForm.Create;
begin
MyThreadReady := false; MyThread := TMyThread.Create(false);
end; procedure TMainForm.Close;
begin
if not MyThreadReady then
begin
MyThread.Terminate;
MyThread.WaitFor;
MyThread.Free;
end;
end;
Thanks!
You can simplify this to:
procedure TMyThread.Execute;
begin
// ... Do some processing
end; procedure TMainForm.Create;
begin
MyThread := TMyThread.Create(false);
end; procedure TMainForm.Close;
begin
if Assigned(MyThread) then
MyThread.Terminate;
MyThread.Free;
end;
Explanation:
Either use
FreeOnTerminateor free the thread manually, but never do both.
The asynchronous nature of the thread execution means that you run a risk of not freeing the thread
or (much worse) doing it twice.There is no risk in keeping the thread object around after it has finished the execution,
and there is no risk in callingTerminate()on a thread that has already finished either.There is no need to synchronize access to a boolean that is only written from one thread and read from another.
In the worst case you get the wrong value, but due to the asynchronous execution that is a spurious effect anyway.
Synchronization is only necessary for data that can not be read or written to atomi
How to terminate anonymous threads in Delphi on application close?
I have a Delphi application which spawns 6 anonymous threads upon some TTimer.OnTimer event.
If I close the application from the X button in titlebar Access Violation at address $C0000005 is raised and FastMM reports leaked TAnonymousThread objects.
Which is the best way to free anonymous threads in Delphi created within OnTimer event with TThread.CreateAnonymousThread() method?
SOLUTION which worked for me:
Created a wrapper of the anonymous threads which terminates them upon being Free-ed.
type
TAnonumousThreadPool = class sealed(TObject)
strict private
FThreadList: TThreadList;
procedure TerminateRunningThreads;
procedure AnonumousThreadTerminate(Sender: TObject);
public
destructor Destroy; override; final;
procedure Start(const Procs: array of TProc);
end; { TAnonumousThreadPool } procedure TAnonumousThreadPool.Start(const Procs: array of TProc);
var
T: TThread;
n: Integer;
begin
TerminateRunningThreads; FThreadList := TThreadList.Create;
FThreadList.Duplicates := TDuplicates.dupError; for n := Low(Procs) to High(Procs) do
begin
T := TThread.CreateAnonymousThread(Procs[n]);
TThread.NameThreadForDebugging(AnsiString('Test thread N:' + IntToStr(n) + ' TID:'), T.ThreadID);
T.OnTerminate := AnonumousThreadTerminate;
T.FreeOnTerminate := true;
FThreadList.LockList;
try
FThreadList.Add(T);
finally
FThreadList.UnlockList;
end;
T.Start;
end;
end; procedure TAnonumousThreadPool.AnonumousThreadTerminate(Sender: TObject);
begin
FThreadList.LockList;
try
FThreadList.Remove((Sender as TThread));
finally
FThreadList.UnlockList;
end;
end; procedure TAnonumousThreadPool.TerminateRunningThreads;
var
L: TList;
T: TThread;
begin
if not Assigned(FThreadList) then
Exit;
L := FThreadList.LockList;
try
while L.Count > do
begin
T := TThread(L[]);
T.OnTerminate := nil;
L.Remove(L[]);
T.FreeOnTerminate := False;
T.Terminate;
T.Free;
end;
finally
FThreadList.UnlockList;
end;
FThreadList.Free;
end; destructor TAnonumousThreadPool.Destroy;
begin
TerminateRunningThreads;
inherited;
end;
End here is how you can call it:
procedure TForm1.Button1Click(Sender: TObject);
begin
FAnonymousThreadPool.Start([ // array of procedures to execute
procedure{anonymous1}()
var
Http: THttpClient;
begin
Http := THttpClient.Create;
try
Http.CancelledCallback := function: Boolean
begin
Result := TThread.CurrentThread.CheckTerminated;
end;
Http.GetFile('http://mtgstudio.com/Screenshots/shot1.png', 'c:\1.jpg');
finally
Http.Free;
end;
end, procedure{anonymous2}()
var
Http: THttpClient;
begin
Http := THttpClient.Create;
try
Http.CancelledCallback := function: Boolean
begin
Result := TThread.CurrentThread.CheckTerminated;
end;
Http.GetFile('http://mtgstudio.com/Screenshots/shot2.png', 'c:\2.jpg');
finally
Http.Free;
end;
end
]);
end;
No memory leaks, proper shutdown and easy to use.
If you want to maintain and exert control over your threads' lifetimes then you should not use anonymous threads.
Maintain a list of TThread instances and free them at shutdown time.
Whilst it is possible to do what you want with anonymous threads,
it's a lot of extra work that brings no real benefits.
I see.
But I still do not get it.
TAnonymousThread is a descendant of TThread.
So I can maintain a list of them and try to terminate them (since the RTL does not do it automatically).
When I try to terminate it says:
Project mtgstudio.exe raised exception class EThread with message 'Thread Error: The handle is invalid (6)'.
Read the docs for the anonymous thread.
You are not allowed to hold a reference to the TThread since it uses FreeOnTerminate.
System.Classes.TThread.CreateAnonymousThread
Creates an instance of an internally derived thread.
CreateAnonymousThread creates an instance of an internally derived TThread that simply will call the anonymous method of typeTProc.
This thread is created as suspended, so you should call the Start method to make the thread run.
The thread is also marked as FreeOnTerminate, so you should not touch the returned instance after calling Start.
It is possible that the instance had run and then has been freed before other external calls or operations on the instance were attempted.
type TProc = reference to procedure;
type TProc = reference to procedure(Arg1: T);
type TProc = reference to procedure(Arg1: T1, Arg2: T2);
type TProc = reference to procedure(Arg1: T1, Arg2: T2, Arg3: T3);
type TProc = reference to procedure(Arg1: T1, Arg2: T2, Arg3: T3, Arg4: T4);
TProc declares a reference to a generic procedure.
Use the TProc type as a reference to a generic procedure.
There are a few variants of TProc type, each accepting a different number of generic arguments.
Correct thread terminate and destroy的更多相关文章
- std::thread “terminate called without an active exception”
最近在使用std::thread的时候,遇到这样一个问题: std::thread t(func); 如果不使用调用t.join()就会遇到 "terminate called whitho ...
- The CLR's Thread Pool
We were unable to locate this content in zh-cn. Here is the same content in en-us. .NET The CLR's Th ...
- delphi.thread.同步
注意:此文只是讲线程间的同步,其它同步不涉及. 线程同步是个好话题,因为写线程经常会遇到,所以就写写自己知道的东西. D里面,同步(特指线程同步)从线程的角度来分,有几种情况: 1:主线程与工作线程的 ...
- JDWP Agent
JDWP Agent Implementation Description Revision History Disclaimer 1. About this Document 1.1 Purpose ...
- Tun/Tap interface tutorial
Foreword: please note that the code available here is only for demonstration purposes. If you want t ...
- Window Linux下实现指定目录内文件变更的监控方法
转自:http://qbaok.blog.163.com/blog/static/10129265201112302014782/ 对于监控指定目录内文件变更,window 系统提供了两个未公开API ...
- loadrunner监控度量项及中文解释
1. Number of Concurrent Users (NCU) 并发用户数 – 在指定时刻,系统观察到的并发用户连接数. 2. Request Per Second (RPS) 每秒处理请求数 ...
- Code Review Checklist
左按:当年需要一份详细的代码评审清单作参考,翻译了此文. 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] General Code Smoke Test 通用测试 Comm ...
- Android选择/拍照 剪裁 base64/16进制/byte上传图片+PHP接收图片
转载请注明出处:http://blog.csdn.net/iwanghang/article/details/65633129认为博文实用,请点赞,请评论,请关注.谢谢! ~ 老规矩,先上GIF动态图 ...
随机推荐
- 使用rsync+inotify+apache做分布式图片服务器的部署方法
图片服务器一般是做成分布式的,但要使得所有的图片服务器的文件一致,可以由一个主服务器将文件推送到各个备份服务器上. rsync:文件差异检查及文件推送 inotify:事件触发,实时检测到添加.删除. ...
- Symfony2学习笔记之数据校验
校验在web应用程序中是一个常见的任务.数据输入到表单需要被校验.数据在被写入数据库之前或者传入一个webservice时也需要被校验. Symfony2 配备了一个Validator 组件,它让校验 ...
- Twitter Storm如何保证消息不丢失
storm保证从spout发出的每个tuple都会被完全处理.这篇文章介绍storm是怎么做到这个保证的,以及我们使用者怎么做才能充分利用storm的可靠性特点. 一个tuple被”完全处理”是什么意 ...
- 把php.exe加入系统环境变量-使用命令行可快速执行PHP命令
有时候在执行长时间运行的脚本程序的时候,浏览器是架不住的.我们就可以使用CMD命令行或者LINUX命令行执行PHP程序 1.把PHP.EXE加入到环境变量,不用每次都进入到PHP的目录 ① 右击我的 ...
- os和os.path模块
Os和os.path模块函数 1. Os模块 函数 描述 文件处理 Mkfifo()/mknod() 创建命名管道/创建文件系统节点 Remove()/unlink() 删除文件 Renam ...
- ansible命令执行模块使用
ansible命令执行模块使用 1.命令执行模块-command 在远程节点上运行命令. 命令模块使用命令名称,接上空格-的分割符作为参数使用,但是不支持管道符和变量等,如果要使用这些,那么可以使用s ...
- VHDL之Port map and open
编SPI的master控制器,使用公司基本的元件,有些端口用不着,恰巧好二哥(不知年龄的数字组组长,本名Holger)来了,于是请教之,告曰open关键词.后来深感自己VHDL水平太水,下了一本电子书 ...
- Camera拍照声设定
在某些国家(比如Japan),为了防止偷拍,强制拍照声是需要从Speaker出来的(即使插入耳机的情况下). 实现该功能比较简单的方法就是将拍照声类型设置为Ringtone 或 Alarm 或 Not ...
- 子元素过滤器nth-child解释
jQuery中的子元素过滤器nth-child是指:选取每个父元素下的第index个子元素或者奇偶元素(index从1算起) 这里有几点要注意: 1. index 从1开始算 2. 过滤器filter ...
- mysql如果搜索长度过宽 导致显示不全的情况解决
今天我在搜索数据库里面优惠码字段 直接使用 select * from table 的命令的时候 由于 第一个 字段过长导致后面的都无法显示全..我还是宽屏! 所以 搜索了一下 可以让 它单行显示 使 ...