AssemblyLoadContext 加载和卸载在不同的函数中得到不同的结果

问题描述

这是微软文档中的代码。请注意代码中的注释

class TestAssemblyLoadContext : AssemblyLoadContext
{
    private AssemblyDependencyResolver _resolver;

    public TestAssemblyLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
    {
        _resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
    }

    protected override Assembly Load(AssemblyName name)
    {
        string assemblyPath = _resolver.ResolveAssemblyToPath(name);
        if (assemblyPath != null)
        {
            return LoadFromAssemblyPath(assemblyPath);
        }
        return null;
    }
}

这是插件接口代码

public interface IPlugin
{
    string result { get; }
}

这是加载和卸载的方法(我修改了microsoft doc中的代码)

private static string pluginPath = @"C:\PluginFolder\MyPlugin.dll"; //interface is IPlugin
private static TestAssemblyLoadContext talc; //the assemblyloadcontext
[MethodImpl(MethodImplOptions.NoInlining)]
static void LoadIt(string assemblyPath)
{
    talc = new PluginFactory.TestAssemblyLoadContext(pluginPath); //create instance
    Assembly a = talc.LoadFromAssemblyPath(assemblyPath); 
    //assemblyPath cant delete now because is loaded
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void UnloadIt()
{
    talc.Unload();
    for (int i = 0; i < 10; i++)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
    //if success unload,file on assemblyPath can success delete.
    File.Delete(assemblyPath);
}

这是 wpf 程序代码的一部分

public MainWindow()
{
    InitializeComponent();

    LoadIt(pluginPath); //loaded assembly
    UnloadIt(pluginPath); //success unload assembly,file assembly can delete.
}

private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}

如果卸载代码与加载代码不在一起

public MainWindow()
{
    InitializeComponent();

    LoadIt(pluginPath); //loaded assembly
}

private void Button_Click(object sender,RoutedEventArgs e)
{
    UnloadIt(pluginPath); //unsuccessful. File assembly cant delete.
}

private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}

但是如果在 Wpf 初始化函数“MainWindow()”或 wpf 应用程序事件中没有调用加载代码,例如Loaded 事件、ContentRendered 事件、Activated 事件,都会起作用。

public MainWindow()
{
    InitializeComponent();
}

private void LoadButton_Click(object sender,RoutedEventArgs e)
{
    LoadIt(pluginPath); //load plugin with button click event.
}

private void UnloadButton_Click(object sender,RoutedEventArgs e)
{
    UnloadIt(pluginPath) //It successful unload,assembly file can be deleted.
}

private static TestAssemblyLoadContext talc;
LoadIt(){...}
UnloadIt(){...}

谁能告诉我为什么?这可能是一个错误吗?

您可以将代码复制到新的 wpf 程序中进行测试。我的运行时框架是 .Net 5

解决方法

嗯,我知道原因了,调试器运行的时候会锁定汇编文件,改成release就好了。

https://github.com/dotnet/runtime/issues/47704

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...