我不得不调用一些写得很糟糕的第 3 方 COM 组件,它们存在内存泄漏并在长时间运行的进程中使用单线程单元 [STA]。
我知道单独的进程将是实现它的好方法,我可以偶尔从长时间运行的进程中重新启动它。
可以改用 AppDomain 吗?如果标记得当,AppDomain 线程是 STA 线程吗?它是否有自己的 COM 对象内存?卸载 AppDomain 是否相当于杀死进程?
AppDomain 不提供与进程相同程度的隔离。事实上,如果您担心 3rd 方组件状态不佳,则存在风险,即它会关闭您的 .NET 应用程序。
如果卸载时正在执行非托管代码,则无法卸载 AppDomain,因此您可能很难控制 AppDomain 中的第 3 方代码。请参阅http://msdn.microsoft.com/en-us/library/system.appdomain.unload.aspx
即使仅对于托管代码,AppDomain 也不提供强大的沙盒解决方案。例如,如果加载的代码产生了任何线程,这些线程将在出现未处理的异常时关闭整个进程。这个问题有更多信息:.NET - What's the best way to implement a "catch all exceptions handler"。
据我所知,在 .NET 应用程序中托管此类代码的最佳选择是实现您自己的 CLR 托管进程,例如 IIS 和 SQL Server。
AppDomain (应用程序域)是应用程序执行的隔离环境。
它们有助于为执行托管代码提供隔离、卸载和安全边界。
使用应用程序域来隔离可能导致进程中断的任务。如果正在执行任务的 AppDomain 的状态变得不稳定,则可以在不影响进程的情况下卸载 AppDomain。当一个进程必须长时间运行而不重新启动时,这一点很重要。您还可以使用应用程序域来隔离不应共享数据的任务。
如果程序集被加载到默认应用程序域中,则无法在进程运行时将其从内存中卸载。但是,如果您打开第二个应用程序域来加载和执行程序集,则在卸载该应用程序域时会卸载程序集。使用此技术可以最大限度地减少偶尔使用大型 DLL 的长时间运行进程的工作集。
多个应用程序域可以在一个进程中运行;但是,应用程序域和线程之间没有一对一的关联。多个线程可以属于单个应用程序域,虽然给定线程不限于单个应用程序域,但在任何给定时间,线程都在单个应用程序域中执行。
SO 可能感兴趣的问题:
我不会自称是 AppDomain 领域的专家,但我相当肯定 COM 对象泄漏内存(即非托管内存)不会通过卸载 AppDomain 来释放。也许对此更熟悉的人可以发表评论。
正如 Brian 所指出的,“......在 .NET Framework 2.0 版域中不能保证卸载,因为它可能无法终止正在执行的线程。”