多线程应用程序中静态全局非托管资源的管理
本文关键字:资源 管理 应用程序 静态 全局 多线程 | 更新日期: 2023-09-27 18:24:27
我们遇到了一个资源管理问题,我们已经挣扎了好几个星期了,虽然我们终于找到了解决方案,但对我来说仍然很奇怪。
我们有大量针对遗留系统开发的互操作代码,该遗留系统公开了一个C API。该系统的许多特性之一是(由于未知的原因),在使用API之前,必须初始化"环境",该"环境"似乎是经过处理的。然而,它只能初始化一次,并且必须在完成后"关闭"
我们最初使用单例模式来实现这一点,但当我们在IIS托管的web服务中使用此系统时,我们的AppDomain偶尔会被回收,从而导致"孤立"环境泄漏内存。由于终结和(显然)甚至IIS回收都是不确定的,在所有情况下都很难检测到,我们已经切换到了一种似乎运行良好的处置+引用计数模式。然而,手动进行引用计数感觉很奇怪,我相信还有更好的方法。
在这样的环境中管理一个静态的全球可支配资源有什么想法吗?
以下是环境管理的大致结构:
public class FooEnvironment : IDisposable
{
private bool _disposed;
private static volatile int _referenceCount;
private static readonly object InitializationLock = new object();
public FooEnvironment()
{
lock(InitilizationLock)
{
if(_referenceCount == 0)
{
SafeNativeMethods.InitFoo();
_referenceCount++;
}
}
}
public void Dispose()
{
if(_disposed)
return;
lock(InitilizationLock)
{
_referenceCount--;
if(_referenceCount == 0)
{
SafeNativeMethods.TermFoo();
}
}
_disposed = true;
}
}
public class FooItem
{
public void DoSomething()
{
using(new FooEnvironment())
{
// environment is now initialized (count == 1)
NativeMethods.DoSomething();
// superfluous here but for our purposes...
using(new FooEnvironment())
{
// environment is initialized (count == 2)
NativeMethods.DoSomethingElse();
}
// environment is initialized (count == 1)
}
// environment is unloaded
}
}
我首先站起来,因为关于您的特定代码库有很多未知之处,但我想知道基于会话的方法有什么好处吗?您可以有一个(线程安全)会话工厂单例,负责确保只初始化一个环境,并通过将其绑定到ASP.NET AppDomain和/或类似平台上的事件来适当地处理该环境。您需要将此会话模型烘焙到API中,以便所有客户端在进行任何调用之前首先建立会话。对这个答案的含糊表示歉意。如果你能提供一些示例代码,也许我可以给出一个更具体/详细的答案。
您可能需要考虑的一种方法是为非托管组件创建一个独立的AppDomain。这样,当IIS托管的AppDomain被回收时,它就不会孤立。