IIS应用程序池回收和本机程序集
本文关键字:本机 程序集 应用 应用程序 程序池 IIS | 更新日期: 2023-09-27 18:25:49
我有一个在IIS下运行的应用程序,该应用程序有三个程序集:托管程序集、混合程序集和本机dll。托管程序集公开了一个单例对象MaS
,该对象通过混合单例MiS
(C++/CLI)封装本机单例NaS
。
问题
当IIS回收应用程序池时,托管的单例MaS
似乎会消失,其程序集从APPDOMAIN卸载,混合的MiS
也是如此。然而,原生单例NaS
仍然存在,并且不会被破坏。在我的情况下,这是有问题的,因为当应用程序被回收并再次加载时,托管单例MaS1
会感到困惑,因为它在内存中发现了一个已经存在的本地单例NaS
。
问题
应用程序池回收时如何处理本机dll?它们被卸载了吗?
Appdomain回收不会卸载Appdomain,而是加载一个新域,后续请求由一个新的Appdomain处理。
旧的appdomain只有在处理完已接受的请求后才会卸载。
如果旧的appdomain在非托管代码中执行阻塞操作,它也可能无法卸载。
作为一种解决方法,您可以禁用apppool回收并配置移动工作进程。独立的工作进程肯定会隔离非托管dll状态。
您可以使用以下代码轻松检查非托管dll是否在应用程序域之间共享其状态:
托管代码:
[DllImport("Win32Library.dll")]
public static extern Int16 inc();
private readonly static DateTime AppDomainStarted = DateTime.UtcNow;
public ActionResult Counter()
{
return new JsonResult { Data = new { counter = inc(), appDomainId = AppDomain.CurrentDomain.Id, started = AppDomainStarted.ToString() }, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
非托管代码:
extern "C" __declspec(dllexport) short inc();
short inc()
{
static int counter = 0;
return counter++;
}
只需重新编译您的aspnet代码并刷新浏览器,即可查看计数器中的递增结果,以及工作流程中的appdomain id。请确保使用IISExpress进行调试。