在加载上下文中加载非托管静态 dll

use*_*245 3 c# .net-core

我有原生的非托管 dll,它是静态的,如果我想并行运行它,每次我需要库来做一些工作时都必须加载它。在 .NET 中,我会使用 AppDomain 并在需要时加载此 dll,但在 NET Core 中 AppDomains 已经消失(目前)。我查看了 AssemblyLoadContext,但没有关于 LoadUnmanagedDll 的适当文档。这可以在netstandard1.6中完成吗?

编辑 当前代码使用 PInvoke 调用并且运行良好。问题是因为这个 unmanged dll 的性质,当我尝试并行调用它时会抛出 AccessViolationException,因为两个或多个任务想要访问相同的内存。

如果我可以在某些上下文中每次加载 dll,然后调用 PInvoke,这个问题就会消失。

Jak*_*ake 5

一种方法:

  1. 派生类 System.Runtime.Loader.AssemblyLoadContext
  2. 覆盖Load(AssemblyName assemblyName)调用LoadFromAssemblyPath()或返回 null 以回退默认上下文
  3. 覆盖IntPtr LoadUnmanagedDll(string unmanagedDllName)调用LoadUnmanagedDllFromPath()以加载您的本机 dll
  4. 间接访问您的 pinvoke 方法并通过一些已知的加载本机/非托管库 interface

第四步是你需要根据现有代码的结构进行调整的部分。就我而言,我创建了 3 个程序集:

  1. 调用代码
  2. 调用代码
  3. 前两者共享的接口

在调用代码中:

var assem = assemblyLoadContext.LoadFromAssemblyName(new 
System.Reflection.AssemblyName(pinvokeAssemblyName));
var type = assem.GetType(nameOfTypeThatCallsPinvoke);
return (ISharedInterface)Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)

nameOfTypeThatCallsPinvoke尝试使用 pinvoke 方法的实例时,您LoadUnmanagedDll()在加载上下文上的覆盖将被调用。

需要共享接口,以便在编译时知道类型。如果调用代码直接引用 pinvoke 库,它的类型将与通过加载上下文获得的类型不同。

参考: