2014-10-07 135 views
1

我有一个在IIS下运行的应用程序,该应用程序有三个程序集:一个托管程序集,一个混合程序集和一个本机DLL。 托管程序集公开一个单例对象MaS,该对象通过混合单例MiS(C++/CLI)打包原生单例NaSIIS应用程序池回收和本地程序集

问题

当IIS回收应用程序池,托管单MaS似乎消失,其装配在AppDomain中卸载也是如此混合一个MiS。但是,原生单身人士NaS坚持并不会被破坏。在我的情况下,这是有问题的,因为当应用程序被回收并再次加载时,受管理的单例现在MaS1会因为在内存中发现已存在的本地单例NaS而感到困惑。

问题

如何机DLL在应用程序池处理回收?他们被卸载了吗?

+0

我不希望非COM本地对象被魔法破坏,因为一些技术上无关的“管理程序集”在AppDomain循环中被卸载。显然,进程内对象将在AppPool(进程)回收中被破坏......这与您的观察矛盾,并使我完全困惑...... – 2014-10-07 06:15:26

+0

@AlexeiLevenkov完全同意你的看法!我认为对.NET调用这些邪恶的二进制文件,程序集是不尊重的。将更新我的文章。谢谢 – GETah 2014-10-07 06:15:47

+0

@AlexeiLevenkov正是!所有被管理的对象都被销毁了,原生的被保留在内存中,并且不会被破坏:( – GETah 2014-10-07 06:17:21

回答

1

应用程序域回收不会卸载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进行调试。

+0

+1。嗯好的,所以当新的应用程序域被加载时,一个新的被管理的单例会被创建而没有它的本地计数器部分,因为它是已经在内存中这是正确的吗?这些应用程序域共享所有加载的本机对象还是每个应用程序域都有自己的一组本机对象? – GETah 2014-10-07 07:28:19

+1

它在工作进程中的所有应用程序域之间共享,您需要回收工作进程以重新初始化。 – 2014-10-07 08:00:45

+0

我想这只适用于IIS配置为加载所有后续的应用程序域到相同的过程权? – GETah 2014-10-07 15:29:32