我在这里写的是在 Github 上发布的同一个问题,因为我最近在那里没有看到太多的流量。
- .NET Core 版本:3.1.9 和 .Net 5
- Windows 版本:10.0.18363
- 该错误是否也在 .NET Framework 4.8 的 WPF 中重现?:不支持 AssemblyLoadContext
我正在尝试按需加载和卸载 Wpf App 库(以及所有相关的依赖项)。一切正常,但在调用 Unload 方法时没有任何程序集被卸载。如果我用包含一些示例方法的 .Net Core 库替换 Wpf 库,我可以看到在几次 GC 迭代后从 VS Modules 窗口中删除了该库。
如果我没记错的话,我应该期望 AssemblyLoadContext 加载 WpfLibrary 和相关依赖项(PresentationCore、PresentationFramework 等),但 WpfLibrary 是唯一加载的。所有其他依赖项似乎都加载到默认上下文中。可能是我误解了它是如何工作的,但在我看来,框架依赖项阻止了卸载。
此外,我不确定我报告的问题是否与this和/或this相关。
我附上了一个结构如下的示例项目:
项目 1(MainApp,一个添加了 System.Windows.Forms 引用以启用消息泵的控制台项目)
class Program
{
class WpfAppAssemblyLoadContext : AssemblyLoadContext
{
public WpfAppAssemblyLoadContext() : base(true) { }
protected override Assembly Load(AssemblyName assemblyName) => null;
}
[MethodImpl(MethodImplOptions.NoInlining),]
public static void TestRun()
{
var context = new WpfAppAssemblyLoadContext();
var assembly = context.LoadFromAssemblyPath($"{Environment.CurrentDirectory}\\WpfLibrary.dll");
var inst = (IProxy) assembly.CreateInstance("WpfLibrary.MainWindow");
inst.ShowWindow();
inst.CloseWindow();
context.Unload();
assembly = null;
context = null;
inst = null;
}
[STAThread,]
static void Main(string[] args)
{
TestRun();
for (var i = 0; i < 100; i++) {
GC.Collect();
GC.WaitForPendingFinalizers();
}
Application.Run();
}
}
项目 2(代理接口)
namespace ProxyInterface
{
public interface IProxy
{
void ShowWindow();
void CloseWindow();
}
}
项目 3(在项目 2 中实现接口的常规 wpf 库)
namespace WpfLibrary
{
public partial class MainWindow : Window, IProxy
{
public MainWindow()
{
InitializeComponent();
}
public void ShowWindow() { Show();}
public void CloseWindow() { Close();}
}
}
UnloadWpfLibrary.zip (“MainApp”文件夹内的解决方案文件)
进一步更新: DotNet 团队将该问题添加到“未来里程碑”中,因此我必须推断他们认为这是一个错误。我不知道我们什么时候会看到 Wpf 与 AssemblyLoadContext 一起工作。似乎有一种解决方法涉及将目标程序集拆分为两个单独的程序集。我附加了带有建议修改的项目,这次卸载了两个程序集之一,但所有其他程序集仍被加载,包括 WpfLibrary。
UnloadWpfLibraryWithWorkaround.zip
我认为对我来说是时候放弃并重新使用 IPC(命名管道)了,尽管我不确定这是否可以成为有效的替代品。可能是我遗漏了一些东西,而更专业的人可以做进一步的进展,并在此处附上正确修改的项目,这对所有想要使用 ALC 加载和卸载 WPF 的用户都有很大的好处。仅按需加载和卸载 wpf 程序集将总共有 4 个项目,这并不完全干净,但如果最终结果相同,那将是可以接受的。