[英]Unloading AssemblyLoadContext .Net 6 Core throws Exception `System.ExecutionEngineException`
I wrote a simplistic plugin manager which works when creating a plugin instance and unloading it right away.我编写了一个简单的插件管理器,它在创建插件实例并立即卸载它时工作。 But when the plugin instance creation and unloading is done from different methods it throws the following exception without any further information:
但是,当插件实例的创建和卸载是通过不同的方法完成时,它会抛出以下异常而没有任何进一步的信息:
"Exception of type 'System.ExecutionEngineException' was thrown."
Any idea what might be going on?知道会发生什么吗? I did check and it does not appear to be due to the creation of the plugin to run on different threads than the unloading of the context.
我确实检查过,这似乎不是因为创建插件以在与卸载上下文不同的线程上运行。
Here is my code:这是我的代码:
public static class PluginManager
{
private static readonly ILogger _logger;
private static readonly Dictionary<string, WeakReference> _weakReferences;
private static List<PluginConfiguration> _pluginConfigurations;
static PluginManager()
{
_logger = LogManager.GetCurrentClassLogger();
_weakReferences = new Dictionary<string, WeakReference>();
}
public static void Configure(List<PluginConfiguration> pluginConfigurations)
{
_pluginConfigurations = pluginConfigurations;
}
public static List<string> GetPluginNames()
{
return _pluginConfigurations.Select(x => x.Name).ToList();
}
public static PluginConfiguration GetPluginConfiguration(string pluginName)
{
return _pluginConfigurations.FirstOrDefault(x => x.Name == pluginName);
}
public static List<PluginConfiguration> GetPluginConfigurations()
{
return _pluginConfigurations;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static T GetPlugin<T>(string pluginName)
{
var assemblyPath = $"{SharedDataModule.CoreConfiguration.PluginRootDirectory}/{pluginName}/bin/Debug/net6.0-windows/{pluginName}.dll";
var alc = new PluginAssemblyLoadContext(assemblyPath);
Assembly assembly = alc.LoadFromAssemblyPath(assemblyPath);
var type = assembly.GetTypes().First(t => t.Name == pluginName);
//store weak reference
_weakReferences[pluginName] = new WeakReference(alc, trackResurrection: true);
//instantiate plugin
var plugin = Activator.CreateInstance(type, _pluginConfigurations.FirstOrDefault(x => x.Name == pluginName));
_logger.Info($"Successfully subscribed to {pluginName} plugin");
return (T)plugin;
}
public static void Unload(string pluginName)
{
if (_weakReferences.ContainsKey(pluginName) == false)
return;
//obtain weak reference
var weakRef = _weakReferences[pluginName];
//try to remove weak reference
_weakReferences.Remove(pluginName);
//unload
((PluginAssemblyLoadContext) weakRef.Target).Unload();
var task = Task.Run(() =>
{
for (var i = 1; weakRef.IsAlive == true && i <= 10; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
Task.Delay(200).Wait();
}
if (weakRef.IsAlive == false)
_logger.Info($"Plugin {pluginName} was successfully unloaded");
else
_logger.Error($"Plugin {pluginName} could not be unloaded");
});
}
private class PluginAssemblyLoadContext : AssemblyLoadContext
{
private readonly string _assemblyToLoadPath;
private readonly AssemblyDependencyResolver _resolver;
public PluginAssemblyLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_assemblyToLoadPath = mainAssemblyToLoadPath;
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.