我有 native 非托管 dll,它是静态的,如果我想并行运行它,每次我需要库来做一些工作时都必须加载它。在 .NET 中,我会使用 AppDomain 并在需要时加载此 dll,但在 NET Core 中,AppDomains 已消失(目前)。我查看了 AssemblyLoadContext,但没有关于 LoadUnmanagedDll 的适当文档。 netstandard1.6 可以做到吗?
编辑 当前使用 PInvoke 调用代码并且运行良好。问题是因为这个未管理的 dll 的性质,当我尝试并行调用它时抛出 AccessViolationException,因为两个或多个任务想要访问相同的内存。
如果我每次都可以在某些上下文中加载 dll,然后调用 PInvoke,这个问题就会消失。
最佳答案
一种方法:
- 从
System.Runtime.Loader.AssemblyLoadContext
派生类 - 覆盖
Load(AssemblyName assemblyName)
调用LoadFromAssemblyPath()
或返回 null 以回退到默认上下文 - 覆盖
IntPtr LoadUnmanagedDll(string unmanagedDllName)
调用LoadUnmanagedDllFromPath()
以加载您的 native dll - 间接访问您的 pinvoke 方法并通过一些已知的
接口(interface)
加载 native /非托管库
第4步是您需要根据现有代码结构进行调整的部分。就我而言,我创建了 3 个程序集:
- 调用代码
- 调用代码
- 前两个共享的接口(interface)
在调用代码中:
var assem = assemblyLoadContext.LoadFromAssemblyName(new
System.Reflection.AssemblyName(pinvokeAssemblyName));
var type = assem.GetType(nameOfTypeThatCallsPinvoke);
return (ISharedInterface)Activator.CreateInstance(type);
当 nameOfTypeThatCallsPinvoke
的实例尝试使用 pinvoke 方法时,将调用加载上下文中的 LoadUnmanagedDll()
覆盖。
需要共享接口(interface),以便在编译时知道类型。如果调用代码直接引用 pinvoke 库,它的类型将不同于通过加载上下文获得的类型。
引用资料:
关于c# - 在加载上下文中加载非托管静态 dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43049370/