应用程序域回收不会卸载appdomain,它将加载一个新域,并且后续请求由新的appdomain处理。
只有在完成处理已接受的请求时,旧appdomain才会卸载。
如果旧的appdomain在非托管代码中执行阻止操作,则也可能无法卸载。
作为解决方法,您可以禁用应用程序池回收并配置过度的工作进程。 单独的工作进程肯定会隔离非托管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进行调试。
我不希望非COM本地对象被魔法破坏,因为一些技术上无关的“管理程序集”在AppDomain循环中被卸载。显然,进程内对象将在AppPool(进程)回收中被破坏......这与您的观察矛盾,并使我完全困惑...... – 2014-10-07 06:15:26
@AlexeiLevenkov完全同意你的看法!我认为对.NET调用这些邪恶的二进制文件,程序集是不尊重的。将更新我的文章。谢谢 – GETah 2014-10-07 06:15:47
@AlexeiLevenkov正是!所有被管理的对象都被销毁了,原生的被保留在内存中,并且不会被破坏:( – GETah 2014-10-07 06:17:21