TForm创建和销毁以及线程的顺序

时间:2013-05-04 17:34:13

标签: multithreading delphi user-interface c++builder

我有一个调用某种形式的函数的线程来更新这个表单。任务完成后,使用Synchronize形成带有结果的线程更新,并且在程序运行时一切正常。

问题发生在线程运行时我关闭程序我遇到了访问冲突。它是由已经发布的线程更新表单引起的。重新排列表单创建顺序(调用Application->CreateForm)后,它工作正常,因为现在保存线程代码的表单是在更新的表单之前创建的。似乎破坏的顺序与创建顺序相反。

我还在表单析构函数中添加了一些代码,以确保在使用线程代码在表单之前销毁表单时终止线程。因此,在表单析构函数中重新排列表单创建顺序和/或代码可以解决问题。

但我有3个问题:

  1. 创建表单的销毁顺序是什么?是否与我现在假设的创建顺序相反?

  2. 是否有更好的方法来完成上述任务 - 在线程完成处理数据后更新表单GUI项目。现在我使用Synchronize从线程本身做到这一点,但有线程经验的人可能有更好的想法。我的另一个想法是甚至删除由编译器生成的一堆CreateForm并手动创建它们,只使用CreateForm创建主表单以更好地控制销毁顺序(正如Rob Kennedy所建议的那样 - {{ 3}})。

  3. 典型应用程序中动态表单创建/销毁的成本是多少?使用表单隐藏并保留在内存中或在关闭时将其销毁是否更好?

1 个答案:

答案 0 :(得分:3)

使用Owner创建组件时,Owner会将您的组件添加到其拥有的组件列表中。这种情况发生在这段代码中:

procedure TComponent.Insert(AComponent: TComponent);
begin
  if FComponents = nil then FComponents := TList<TComponent>.Create;
  FComponents.Add(AComponent);
  if FSortedComponents <> nil then
    AddSortedComponent(AComponent);
  AComponent.FOwner := Self;
end;

如您所见,该组件已添加到列表的末尾。

当所有者被销毁时,它会调用DestroyComponents

procedure TComponent.DestroyComponents;
var
  Instance: TComponent;
begin
  FreeAndNil(FSortedComponents);
  while FComponents <> nil do
  begin
    Instance := FComponents.Last;
    if (csFreeNotification in Instance.FComponentState)
      or (FComponentState * [csDesigning, csInline] = [csDesigning, csInline]) then
      RemoveComponent(Instance)
    else
      Remove(Instance);
    Instance.Destroy;
  end;
end;

如您所见,循环首先处理最后一个成员。因此,组件以相反的顺序销毁。

我个人不会依赖销毁令。如果表单需要确保在销毁表单之前终止线程,我会在表单的析构函数中编写代码来强制执行该操作。

使用Synchronize是解决许多问题的完美方案。无论是否是解决问题的最佳方案,我都不可能说,因为您还没有完全描述您的问题。

  

典型应用程序中动态表单创建/销毁的成本是多少?

不是很好。通常,表单是响应于用户交互而示出的。程序可以比用户处理表单更快地创建表单。因此,动态创建表单很少是个问题。如果你想创建并销毁数以千计的表单,这可能是一个问题。但那会很奇怪。