如何释放Activator.CreateInstance创建的实例以解决插件进程无法正常关闭问题
核心原因说明
你目前遇到的进程驻留问题和Activator.CreateInstance()本身没有直接关系,默认通过Assembly.Load()加载到当前应用域的程序集无法单独卸载,只有整个应用域退出时才会释放相关资源。你将实例置空后调用GC不生效,大概率是存在以下几种情况:
- 插件内部启动了未终止的前台线程,前台线程存活会直接阻止进程退出
- 插件实例持有你传入的主程序对象(也就是你代码里的
this)的引用,且引用链路没有断开 - 插件注册了全局事件、静态回调没有取消,导致引用被全局资源持有
解决方案
- 第一步:定义标准化插件释放接口
先定义统一的插件接口要求所有插件实现,示例如下:
插件实现public interface IPluginModule { void Release(); }Release方法时,需要主动停止所有后台/前台线程、取消已订阅的事件、清空持有的主程序引用、释放所有非托管资源。主程序关闭前遍历所有已加载的插件实例,调用Release方法。 - 第二步:断开所有引用链路
你目前创建实例时传入了this,要确保插件不会将该引用存储为静态变量,静态变量的引用不会随实例置空而释放,必须在Release方法中手动置空。所有存储插件实例的全局集合,在主程序关闭时也要清空。 - 第三步:如需支持热卸载插件,使用独立加载上下文
如果你使用的是.NET Framework,可以将插件加载到独立的AppDomain中,不需要插件时直接卸载整个AppDomain即可完全释放所有插件相关资源。
如果你使用的是.NET Core/.NET 5+,使用可卸载的AssemblyLoadContext加载插件,示例如下:// 创建支持卸载的插件加载上下文 var pluginContext = new AssemblyLoadContext("CustomPluginContext", isCollectible: true); using var fileStream = File.OpenRead("你的插件.dll路径"); Assembly pluginAssembly = pluginContext.LoadFromStream(fileStream); // 创建实例逻辑和原有逻辑一致 Type type = pluginAssembly.GetType("ModularModule.ModularModule"); object instance = Activator.CreateInstance(type, new object[] { this }); // 需要卸载时执行 pluginContext.Unload(); // 主动触发GC回收残留资源 GC.Collect(); GC.WaitForPendingFinalizers(); - 兜底方案:主程序关闭时强制退出
如果你已经完成所有资源释放操作仍有进程驻留,可以在主窗口关闭事件的最后调用Environment.Exit(0),会直接终止当前进程所有线程,确保进程完全退出。
内容的提问来源于stack exchange,提问作者Meme Machine
相关产品推荐
相关产品推荐

