3

在我的程序中,我可以加载目录:Icatalog

此处的目录包含很多引用结构(Icollections of IItems、IElements、IRules 等)

当我想更改到另一个目录时,我加载了一个新目录,但前一个 IDatalog 实例的自动释放需要时间,我的应用程序冻结了 2 秒或更长时间。

我的问题是:

我想将旧的(不再使用的)ICatalog 实例的发布推迟到另一个线程。

我还没有测试过,但我打算创建一个新线程:

ErazerThread.OldCatalog := Catalog; // old catalog refcount jumps to 2
Catalog := LoadNewCatalog(...);     // old catalog refcount =1
ErazerThread.Execute;               //just set OldCatalog to nil.

这样,我希望发布发生在线程中,并且我的应用程序不再冻结。

它安全(和良好的做法)吗?
您是否有已经使用类似方法执行发布的现有代码示例?

4

2 回答 2

2

看起来不错,但不要Execute直接调用线程的方法;这将在当前线程中运行线程对象的代码,而不是线程对象创建的代码。打电话StartResume代替。

于 2011-10-19T14:53:37.140 回答
2

我会让这样的线程阻塞在某个线程安全队列(*)上,并将接口作为 iunknowns 推送到该队列中。

但是请注意,如果释放触及您的内存管理器使用的锁(如全局堆管理器锁),那么这是徒劳的,因为您的主线程将在第一次堆管理器访问时阻塞。

使用具有每个线程池的堆管理器,在一个线程中分配许多项目并在不同的线程中释放它可能会阻碍(小)块算法的合并和重用。

我仍然认为您描述的方式在正确实施时通常是合理的。但这是从理论的角度来看,表明可能存在从第二个线程通过堆管理器到主线程的链接。

(*) 最简单的方法是将其添加到 tthreadlist 并使用 tevent 来表示添加了一个元素。

于 2011-10-19T16:55:50.010 回答