线程设置为运行结束时自动释放实例的FreeOnTerminate=true,如何检测所有生成的线程全部释放,多谢 ( 积分: 200 )

  • 主题发起人 主题发起人 wzhiwei
  • 开始时间 开始时间
W

wzhiwei

Unregistered / Unconfirmed
GUEST, unregistred user!
线程设置为运行结束时自动释放实例的FreeOnTerminate=true
如何检测所有生成的线程全部释放,多谢
线程的数量是动态生成的
 
线程设置为运行结束时自动释放实例的FreeOnTerminate=true
如何检测所有生成的线程全部释放,多谢
线程的数量是动态生成的
 
希望以下这段转发代码会对你有所帮助。
--------------------------
// 获取用户组线程
TGetUserGroupsThead = class(TThread)
private
FOwnerHandle: HWND;
FUnitId: WideString;
FParentNode, tmpParentNode: TTreeNode;
FtvUnits: TTreeView;
FRecursive: Boolean;
FIsExpandAll: Boolean;
FRIO: TMyRIO;
// 私有变量
aUserGroup: TUserGroup;
p: ^TObject;
aNode: TTreeNode;
// 线程结束时通知父窗口
procedure FinalAct(Sender: TObject);
// 查询
procedure ListChildNode(parentId: String;
parentNode: TTreeNode);
// 同步添加节点
procedure AddNode;
protected
// 线程执行体
procedure Execute;
override;
public
// 构造函数
constructor Create(// 所有者窗口句柄
const OwnerHandle: HWND;
// 远程操作组件
RIO: TMyRIO;
// 单元ID
UnitId: WideString;
// 是否查询子单元
IsRecursive: Boolean;
// 父节点
ParentNode: TTreeNode;
// 节点
tvUnits: TTreeView;
// 是否全部展开
IsExpandAll: Boolean=true);
end;

{ TGetUserGroupsThead }
// 操作VCL组件,该方法必须同步调用
procedure TGetUserGroupsThead.AddNode;
begin
aNode := FtvUnits.Items.AddChildObject(tmpParentNode, aUserGroup.UnitName, p);
if FIsExpandAll then
tmpParentNode.Expand(True);
end;

constructor TGetUserGroupsThead.Create(const OwnerHandle: HWND;
RIO: TMyRIO;
UnitId: WideString;
IsRecursive: Boolean;
ParentNode: TTreeNode;
tvUnits: TTreeView;
IsExpandAll: Boolean);
begin
FOwnerHandle := OwnerHandle;
FRIO := RIO;
FUnitId := UnitId;
FRecursive := IsRecursive;
FParentNode := ParentNode;
FtvUnits := tvUnits;
FIsExpandAll := IsExpandAll;
OnTerminate := FinalAct;
FreeOnTerminate := True;
inherited Create(False);
end;

procedure TGetUserGroupsThead.Execute;
begin
CoInitialize(nil);
ListChildNode(FUnitId, FParentNode);
end;

procedure TGetUserGroupsThead.FinalAct(Sender: TObject);
begin
// 通知窗口线程已经结束
PostMessage(FOwnerHandle, WM_GetUnitsTheadDoneMsg, 0, 0);
end;

procedure TGetUserGroupsThead.ListChildNode(parentId: String;
parentNode: TTreeNode);
var
rs: ArrayOf_tns1_UserGroup;
i: Integer;
begin
// 下面是通过WebService取得用户组列表,你不用管
FRIO.Acquire;
try
rs := FRIO.ua.userGroupSearchUserGroups(FRIO.UserAuthConnection.LoginId,
FRIO.UserAuthConnection.LoginPwd, parentId, UA_FALSE);
finally
FRIO.Release;
end;
// 递归添加树型节点,因为只能每次取得当前节点的子节点所以使用了递归(服务器端接口的限制)
for i := Low(rs) to High(rs)do
begin
aUserGroup := TUserGroup.Create;
aUserGroup.aUserGroup := rs;
aUserGroup.UserAuthConnection := FRIO.UserAuthConnection;
new(p);
p^ := aUserGroup;
tmpParentNode := parentNode;
// 使用同步方法添加到form上的TreeView控件中
Synchronize(AddNode);
aUserGroup.Owner := aNode;
if FRecursive then
ListChildNode(aUserGroup.UserGroupId, aNode);
end;
end;
 
动态创建线程,用TList来记录!最后检查
 
用WaitForSingleObject等一下就知道了
if (WaitForSingleObject(AThread.Handle,1000) == Wait_Object_0)//
这表示线程终止了
如果多个线程可用WaitForMutiObject,第一个参数为多个线程数组的首址,第二个参数如果为 WAIT_ALL表示等所有的线程
 
china_jian
动态创建线程,用TList来记录!最后检查
大侠,可以给个示例函数吗 多谢了
 
就是用个数组(或TList)来保存你所创建线程的Thread.Handle,
 用WaitForSingleObject依次等,如果用WaitForMutiObject效率高一些
 
WaitForMultipleObjects 怎么用啊 多谢了
 
函数WaitForMultipleObjects可以同时监测多个同步对象,该函数的声明为:
DWORD WaitForMultipleObjects(DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds );
 
参数nCount是句柄数组中句柄的数目。lpHandles代表一个句柄数组。bWaitAll说明了等待类型,如果为TRUE,那么函数在所有对象都有信号后才返回,如果为FALSE,则只要有一个对象变成有信号的,函数就返回。函数的返回值在表12.2中列出。参数dwMilliseconds是以毫秒为单位的超时间隔,如果该参数为0,那么函数就测试同步对象的状态并立即返回,如果该参数为INFINITE,则超时间隔是无限的。
 
表12.2 WaitForMultipleObjects的返回值
返回值 说明
WAIT_OBJECT_0到WAIT_ OBJECT_0+nCount-1 若bWaitAll为TRUE,则返回值表明所有对象都是有信号的。如果bWaitAll为FALSE,则返回值减去WAIT_OBJECT_0就是数组中有信号对象的最小索引。
WAIT_ABANDONED_0到WAIT_ ABANDONED_ 0+nCount-1 若bWaitAll为TRUE,则返回值表明所有对象都有信号,但有一个mutex被放弃了。若bWaitAll为FALSE,则返回值减去WAIT_ABANDONED_0就是被放弃mutex在对象数组中的索引。
WAIT_TIMEOUT 超时返回。
 
 
CONST HANDLE *lpHandles 这个参数怎么用啊
比如 我创建了一个 ThreadList: TList;
使用 ThreadList.Add(TMyThread.Create(ID));
如何写检测是否完成的线程
if WaitForMultipleObjects(ThreadList.Count, @ThreadList, True, INFINITE)
<> WAIT_OBJECT_0 + ThreadList.Count - 1 then
begin
// 判断此时所有的线程没有结束
end
这样写对吗?
 
在构造函数中,将自身加入一个链表,
析构时,从此链表中删除, 用TList 就可以
注意,保护临界区变量,互斥访问,包括主线程
使用 TThreadList 也可以
 
var
ThreadList: TList;
添加:
ThreadList.Add(Pointer(TMyThread.Create(False).Handle));
判断:
if WaitForMultipleObjects(ThreadList.Count, @ThreadList.List, True, INFINITE) then
 

Similar threads

D
回复
0
查看
802
DelphiTeacher的专栏
D
D
回复
0
查看
747
DelphiTeacher的专栏
D
D
回复
0
查看
696
DelphiTeacher的专栏
D
后退
顶部