无法卸载程序集,不确定原因

更新:我设法将其导入WinDbg,并查看发生了什么。我发现了两件事:首先,此列表未正确发布:

private Stack<DependencyAssemblyLoadContext> _loadedContexts;

所以我取消了它,绕过我的GC调用(我知道不好的作法,但是,嘿,这只是一个POC /演示。我担心以后会做得更好。),其中之一我的两个示例DLL已卸载。 (我也将一些列表变成了堆栈,我可以尝试使它们尽快消失。同样,跳过循环,以便将概念演示给人们。)

不过,我注意到的另一件事是,一个示例任务(引发异常)仍然存在。 WinDbg产生以下内容:

0:009> !gcroot -all 0000025e8fc0ffa8
Thread 5824:
    000000F0F237E5F0 00007FFDC9361EAE CleanupService.NetCore.Program.Run() [C:\stuff\Program.cs @ 69]
        rbp-b0: 000000f0f237e630
            ->  0000025E8FC12CB0 System.NotImplementedException
            ->  0000025E8FC16230 System.Object[]
            ->  0000025E8FC0FFA8 System.Reflection.LoaderAllocator

    000000F0F237E5F0 00007FFDC9361EAE CleanupService.NetCore.Program.Run() [C:\stuff\Program.cs @ 69]
        rbp-88: 000000f0f237e658
            ->  0000025E8FC111C8 System.RuntimeType
            ->  0000025E8FC0FFA8 System.Reflection.LoaderAllocator

    000000F0F237E5F0 00007FFDC9361EAE CleanupService.NetCore.Program.Run() [C:\stuff\Program.cs @ 69]
        rbp-78: 000000f0f237e668
            ->  0000025E8FC11268 CleanupService.Sample.SimpleFailedTask
            ->  0000025E8FC0FFA8 System.Reflection.LoaderAllocator

如果我没看错,那么异常本身就留在内存中了吗?并且由于它来自试图卸载的程序集中的类,因此程序集不会卸载。

这似乎...很奇怪。如何摆脱异常引用?

此问题的原始说明如下,但是我更新了下面的代码。


我有一个系统的POC,该系统可以扫描一堆DLL,从中加载任务,然后卸载它们。这是.NET Core 3.0,因此我正在使用AssemblyLoadContext。我一切正常,并且Unloading事件触发,但是当我看着“模块”窗口时,DLL仍然保持加载状态。这与基于AppDomain的CLR版本形成鲜明对比,后者在域被删除后即从“模块”窗口中卸载DLL。

我认为我在某处引用了某些内容,但由于公司对管理员权限的限制,我无法弄清哪里,而WinDbg还是很不稳定。

主要应用:

private IFileSystemService _fileSystemService;
private ITaskManagementService _taskManagementService;

static void Main(string[] args)
{
    new Program().Run();
}

public Program()
{
    _fileSystemService = new FileSystemService();
    _taskManagementService = new TaskManagementService();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public void Run()
{
    Console.WriteLine("Getting available files...");
    var files = _fileSystemService.GetFilePaths("*.dll");
    Console.WriteLine($"Found {files.Length} files to scan.");

    Console.WriteLine("Scanning for tasks...");
    var tasks = _taskManagementService.GetavailablecleanupTasks(files);
    Console.WriteLine($"Total tasks found: { tasks.Count() }");

    while (tasks.Count > 0)
    {
        var task = tasks.Pop();

        Console.WriteLine($"Executing task: { task.GetType().Name }");
        Console.WriteLine("Output:");

        Console.ForegroundColor = ConsoleColor.Green;

        try
        {
            task.Execute<object>();
        }
        catch (Exception ex)
        {
            ex = null;
            continue;
        }
        finally
        {
            Console.ForegroundColor = ConsoleColor.Gray;
            task = null;
        }
    }

    Console.WriteLine("Cleaning up... ");
    _taskManagementService.UnloadAssemblies();
    _taskManagementService = null;
    Console.WriteLine("Cleanup done.");

    GC.WaitForPendingFinalizers();
    GC.Collect();

    Console.WriteLine("Process complete.  Press any key to continue.");
    Console.ReadKey();
}

这是TaskManagementService,用于加载和卸载程序集:

private Stack<DependencyAssemblyLoadContext> _loadedContexts;

public TaskManagementService()
{
    _loadedContexts = new Stack<DependencyAssemblyLoadContext>();
}

public Stack<ICleanupTask> GetavailablecleanupTasks(string[] assemblyPaths)
{
    // This application is designed to run every 24 hours,so just unload what we have before reloading
    UnloadAssemblies();

    var results = new Stack<ICleanupTask>();

    // Loads the assembly containing the task loader so it can be used.  The assembly also contains ICleanupTask and CleanupTask.
    foreach (var path in assemblyPaths)
    {
        var context = new DependencyAssemblyLoadContext(path);
        var assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(path));
        var assembly = context.LoadFromAssemblyName(assemblyName);

        foreach (var task in GetTasksFromAssembly(assembly))
        {
            results.Push(task);
        }

        _loadedContexts.Push(context);
    }

    return results;
}

public void UnloadAssemblies()
{
    if (_loadedContexts.Count == 0)
    {
        return;
    }

    while (_loadedContexts.Count > 0)
    {
        var context = _loadedContexts.Pop();
        // context.Unloading += (e) => Console.WriteLine($"Assembly {e.Assemblies.First().GetName()} unloading...");
        context.Unload();
        context = null;
    }
}

private List<ICleanupTask> GetTasksFromAssembly(Assembly assembly)
{
    var tasks = new List<ICleanupTask>();

    foreach (var type in assembly.GetTypes())
    {
        if (type.IsSubclassOf(typeof(CleanupTask)))
        {
            tasks.Add(Createtask(type));
        }
    }

    return tasks;
}

private ICleanupTask Createtask(Type taskType)
{
    return (ICleanupTask)activator.CreateInstance(taskType);
}
xianggujidan 回答:无法卸载程序集,不确定原因

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3120882.html

大家都在问