c# - AssemblyLoadContext 未正确卸载
问题描述
我对 in 中的方法有奇怪Unload
的问题AssemblyLoadContext
。原始代码来自https://github.com/dotnet/coreclr/pull/22221/files/a7cbc5c8d1bd48cafec48ac50900ff9e96c1485c#diff-cf594171be5712641ea4416aadc2f83f我正在使用 dotnet core 3.0.100-preview3-010431
在这种情况下效果很好:
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
namespace example
{
class TestAssemblyLoadContext : AssemblyLoadContext
{
public TestAssemblyLoadContext() : base(true)
{
}
protected override Assembly Load(AssemblyName name)
{
return null;
}
}
class Manager
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void Execute(out WeakReference testAlcWeakRef)
{
var alc = new TestAssemblyLoadContext();
testAlcWeakRef = new WeakReference(alc);
alc.Resolving += (alc2, assemblyName) =>
{
var dllName = assemblyName.Name.Split(',').First();
return alc2.LoadFromAssemblyPath(@"absolute\path\lib.dll");
};
Assembly a = alc.LoadFromAssemblyPath(@"absolute\path\lib.dll");
var args = new object[] { 3, 2 };
var methodInfo = a.GetExportedTypes()[0].GetMethods().Where(m => m.Name == "MethodName").ToList()[0];
var result = methodInfo.Invoke(Activator.CreateInstance(a.GetExportedTypes()[0]), args);
alc.Unload();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void Unload(WeakReference testAlcWeakRef)
{
for (int i = 0; testAlcWeakRef.IsAlive && (i < 10); i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"is alive: {testAlcWeakRef.IsAlive}");
}
}
class Program
{
static void Main(string[] args)
{
var manager = new Manager();
manager.Execute(out var testAlcWeakRef);
manager.Unload(testAlcWeakRef);
}
}
}
Unload
但我稍后需要调用方法。所以我搬进alc.Unload()
去了manager.Unload()
,alc.Unload()
没有工作。我做错了什么?
不工作的情况:
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
namespace example
{
class TestAssemblyLoadContext : AssemblyLoadContext
{
public TestAssemblyLoadContext() : base(true)
{
}
protected override Assembly Load(AssemblyName name)
{
return null;
}
}
class Manager
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void Execute(out WeakReference testAlcWeakRef, out TestAssemblyLoadContext alc)
{
alc = new TestAssemblyLoadContext();
testAlcWeakRef = new WeakReference(alc);
alc.Resolving += (alc2, assemblyName) =>
{
var dllName = assemblyName.Name.Split(',').First();
return alc2.LoadFromAssemblyPath(@"absolute\path\lib.dll");
};
Assembly a = alc.LoadFromAssemblyPath(@"absolute\path\lib.dll");
var args = new object[] { 3, 2 };
var methodInfo = a.GetExportedTypes()[0].GetMethods().Where(m => m.Name == "MethodName").ToList()[0];
var result = methodInfo.Invoke(Activator.CreateInstance(a.GetExportedTypes()[0]), args);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void Unload(WeakReference testAlcWeakRef, TestAssemblyLoadContext alc)
{
alc.Unload();
for (int i = 0; testAlcWeakRef.IsAlive && (i < 10); i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"is alive: {testAlcWeakRef.IsAlive}");
}
}
class Program
{
static void Main(string[] args)
{
var manager = new Manager();
manager.Execute(out var testAlcWeakRef, out var alc);
manager.Unload(testAlcWeakRef, alc);
}
}
}
解决方案
从文档中:
备注:
- 一个 AssemblyLoadContext 只能在它是可收集的情况下被卸载。
- 卸载将异步进行。
- 存在对 AssemblyLoadContext 的引用时不会发生卸载。
您的alc变量正在阻止卸载上下文。
可能的解决方案:
[MethodImpl(MethodImplOptions.NoInlining)]
public void Unload(WeakReference testAlcWeakRef, ref TestAssemblyLoadContext alc)
{
alc.Unload();
alc = null;
for (int i = 0; testAlcWeakRef.IsAlive && (i < 10); i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"is alive: {testAlcWeakRef.IsAlive}");
}
推荐阅读
- azure-devops - 为什么“项目有效用户”组无权查看项目?
- java - Java 清单中的运行时版本信息
- powerapps-canvas - 如何在 Power Apps 的重复表中保存级联下拉值
- reactjs - 使用 reactjs 中的 firebase 中的新字段更新现有文档
- javascript - React 组件重新无限渲染
- html - 带左右角导航的全宽导航栏
- r - 尝试使用 pak 安装 pkgdown 开发版本时,在 GitHub 操作中安装 rlang 失败
- r - rjags 无法加载并且 R 无法找到任何版本的 JAGS
- r - 在 2 个字符串之间添加空格
- vba - VBA Web Scraping:当ie.visible = False时单击下载栏(保存文件)