1

我在这里写的是在 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 个项目,这并不完全干净,但如果最终结果相同,那将是可以接受的。

4

0 回答 0