IIS应用程序池回收和本机程序集

本文关键字:本机 程序集 应用 应用程序 程序池 IIS | 更新日期: 2023-09-27 18:25:49

我有一个在IIS下运行的应用程序,该应用程序有三个程序集:托管程序集、混合程序集和本机dll。托管程序集公开了一个单例对象MaS,该对象通过混合单例MiS(C++/CLI)封装本机单例NaS

问题

当IIS回收应用程序池时,托管的单例MaS似乎会消失,其程序集从APPDOMAIN卸载,混合的MiS也是如此。然而,原生单例NaS仍然存在,并且不会被破坏。在我的情况下,这是有问题的,因为当应用程序被回收并再次加载时,托管单例MaS1会感到困惑,因为它在内存中发现了一个已经存在的本地单例NaS

问题

应用程序池回收时如何处理本机dll?它们被卸载了吗?

IIS应用程序池回收和本机程序集

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进行调试。