总览
我需要绑定一个具有4个主要函数的本地API:
void ActivateEngine();
int CreateModule();
void DestroyModule(int id);
void TerminateEngine();
文档说明应该在调用CreateModule
和DestroyModule
时使用ActivateEngine
和TerminateEngine
。使用方法应该类似于:
void foo()
{
ActivateEngine();
int module1 = CreateModule();
int module2 = CreateModule();
...
DestroyModule(module2);
DestroyModule(module1);
TerminateEngine();
}
为了实现这一点,我创建了两个.NET对象,即
Engine
和Module
,两者都使用DllImport
属性绑定到本机API。
Engine
对象作为单例模式,绑定到ActivateEngine
和TerminateEngine
。
Module
对象用于在Engine
中创建许多实例,并绑定到本机API中的CreateModule
和DestroyModule
。遇到的问题:
我已经按照用户可以直接创建
Modules
的方式实现了很多内容,而不需要太关注Engine
或对象的生命周期(即我不想强制用户在不再使用时处理对象)。为此,我在
Engine
对象中使用了一个指向所有创建的Modules
的WeakReference
列表。
请看我简化后的代码这里。
问题在于当应用程序结束时,终结器以不确定的方式被调用,并且即使Module
的终结器尚未被调用,WeakReference
目标已经为null并且参数trackResurrection
设置为true。
在我的情况下,代码记录如下:
ActivateEngine() ...
CreateModule() ==> 0 ...
CreateModule() ==> 1 ...
DestroyModule(1) ...
Ooops ... Can't dispose registered module because WeakReference to it is already null ...
Ooops ... Can't dispose registered module because WeakReference to it is already null ...
TerminateEngine() ...
DestroyModule(0) ...
当然,这是不恰当的顺序。
问题
如何强制所有的
Module
在Engine
之前完成?我真的不想强迫最终用户调用
Module
对象上的Dispose
方法,也不想保留对已创建的Module
的强引用,以便在代码中不再引用时自动消失。例如: processing
{
var module = new Module();
...
}
foo()
{
processing();
GC.Collect(); // If using strong references 'module' is gonna be kept alive (that's not smart)
}
我查看了以下使用 ConditionalWeakTable
的线程:
- C# WeakReference object is NULL in finalizer although still strongly referenced
- Get list of active items from ConditionalWeakTable
但我不明白这如何帮助我解决我的问题。