.Net core 的热插拔机制的深入摸索及卸载问题求救(2)

2. Load和LoadUnmanagedDll函数实际上是给开拓者手动加载措施集利用的,
自动加载应放到Resolving和ResolvingUnmanagedDll事件中
原因是,这样的加载顺序不会导致项目标措施集包围插件的措施集,造成措施集加载失败.

3. 手动加载时可以按照deps.json文件界说的runtime加载当前平台下的unmanaged dll文件.

这些平台相关的dll文件,一般位于宣布目次中的runtimes文件夹中.

四.插件项目必然要和主项目利用同样的运行时.

假如主项目是.net core 3.1,插件项目不能选择.net core 2.0等,甚至不能选择.net standard库

不然会呈现不行预知的问题.

插件是.net standard需要修改项目文件,<TargetFrameworks>netstandard;netcoreapp3.1</TargetFrameworks>

这样就可以宣布为.net core项目.

若主项目中的nuget包不适合当前平台,则会报Not Support Platform的异常.这时假如主项目是在windows上, 就需要把项目宣布方针配置为win-x64.这属于nuget包依赖干系存在错误描写.

五.AssemblyLoadContext.UnLoad()并不会抛出任何异常.

当你挪用AssemblyLoadContext.UnLoad()卸载完插件觉得相关措施集已经释放,那你大概就错了.官方文档表白卸载执行失败会抛出InvalidOperationException,不答允卸载。
但实际测试中,卸载失败,但并未报错.

六.反射措施集相关变量的界说为何阻止插件措施集卸载?

插件

namespace PluginSample { public class SimpleService { public void Run(string name) { Console.WriteLine($"Hello World!"); } } }

加载插件

namespace Test { public class PluginLoader { pubilc AssemblyLoadContext assemblyLoadContext; public Assembly assembly; public Type type; public MethodInfo method; public void Load() { assemblyLoadContext = new PluginLoadContext("插件文件夹"); assembly = alc.Load(new AssemblyName("PluginSample")); type = assembly.GetType("PluginSample.SimpleService"); method=type.GetMethod() } } }

1. 在主项目措施中.AssemblyLoadContext,Assembly,Type,MethodInfo等不能直接界说在任何类中.
不然在插件卸载时会失败.其时为了测试是否卸载乐成,回收手动加载,执行,卸载了1000次,
发明内存一直上涨,则暗示卸载失败.

2. 参照官方文档后相识了WeakReferece类.利用该类与AssemblyLoadContext关联,当手动GC清理时,
AssemblyLoadContext就会变为null值,假如没有变为null值则暗示卸载失败.

3. 利用WeakReference关联AssemblyLoadContext并判定是否卸载乐成

public void Load(out WeakReference weakReference) { var assemblyLoadContext = new PluginLoadContext("插件文件夹"); weakReference = new WeakReference(pluginLoadContext, true); assemblyLoadContext.UnLoad(); } public void Check() { WeakReference weakReference=null; Load(out weakReference); //一般第二次,IsAlive就会变为False,即AssemblyLoadContext卸载失败. for (int i = 0; weakReference.IsAlive && (i < 10); i++) { GC.Collect(); GC.WaitForPendingFinalizers(); } }

4. 为了办理以上问题.可以把需要的变量放到静态字典中.在Unload之前把对应的Key值删除去,即可.

七.措施集的异步函数执行为何会阻止插件措施的卸载?

public class SimpleService { //同步执行,插件卸载乐成 public void Run(string name) { Console.WriteLine($"Hello {name}!"); } //异步执行,卸载乐成 public Task RunAsync(string name) { Console.WriteLine($"Hello {name}!"); return Task.CompletedTask; } //异步执行,卸载乐成 public Task RunTask(string name) { return Task.Run(() => { Console.WriteLine($"Hello {name}!"); }); } //异步执行,卸载乐成 public Task RunWaitTask(string name) { return Task.Run( async ()=> { while (true) { if (CancellationTokenSource.IsCancellationRequested) { break; } await Task.Delay(1000); Console.WriteLine($"Hello {name}!"); } }); } //异步执行,卸载乐成 public Task RunWaitTaskForCancel(string name, CancellationToken cancellation) { return Task.Run(async () => { while (true) { if (cancellation.IsCancellationRequested) { break; } await Task.Delay(1000); Console.WriteLine($"Hello {name}!"); } }); } //异步执行,卸载失败 public async Task RunWait(string name) { while (true) { if (CancellationTokenSource.IsCancellationRequested) { break; } await Task.Delay(1000); Console.WriteLine($"Hello {name}!"); } } //异步执行,卸载失败 public Task RunWaitNewTask(string name) { return Task.Factory.StartNew(async ()=> { while (true) { if (CancellationTokenSource.IsCancellationRequested) { break; } await Task.Delay(1000); Console.WriteLine($"Hello {name}!"); } },TaskCreationOptions.DenyChildAttach); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdfff.html