在加载上下文中加载非托管静态 dll [英] Load unmanaged static dll in load context

查看:33
本文介绍了在加载上下文中加载非托管静态 dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have native unmanaged dll which is static and must be loaded each time when I need library to do some work if i want to run it in parallel. In .NET I would use AppDomain and load this dll when i need it, but in NET Core AppDomains are gone (for now). I have looked at AssemblyLoadContext but there is no proper documentation with LoadUnmanagedDll. Can this be done in netstandard1.6?

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

Edit Currently code is called with PInvoke and is working perfectly. Problem is because nature of this unmanged dll, when I try to call it in parallel throws AccessViolationException because two or more task wants to access same memory.

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

If I could load dll for each time that in some context and then call PInvoke on that this problem would be gone.

推荐答案

一种方法:

  1. System.Runtime.Loader.AssemblyLoadContext 派生类
  2. 覆盖 Load(AssemblyName assemblyName) 调用 LoadFromAssemblyPath() 或返回 null 以回退到默认上下文
  3. 覆盖 IntPtr LoadUnmanagedDll(string unmanagedDllName) 调用 LoadUnmanagedDllFromPath() 来加载你的原生 dll
  4. 间接访问您的 pinvoke 方法并通过一些已知的接口
  5. 加载本机/非托管库
  1. Derive class from System.Runtime.Loader.AssemblyLoadContext
  2. Override Load(AssemblyName assemblyName) calling LoadFromAssemblyPath() or returning null to fallback on default context
  3. Override IntPtr LoadUnmanagedDll(string unmanagedDllName) calling LoadUnmanagedDllFromPath() to load your native dll
  4. Indirectly access your pinvoke methods and load the native/unmanaged library through some known interface

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

Step 4 is the part you need to adjust based on the structure of the existing code. In my case, I created 3 assemblies:

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

在调用代码中:

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

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

When instance of nameOfTypeThatCallsPinvoke attempts to use pinvoke method your LoadUnmanagedDll() override on the load context will get called.

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

The shared interfaces are needed so types are known at compile-time. If the calling code references the pinvoke library directly it's types will differ from those obtained through the load context.

参考文献:

  • AssemblyLoadContext design doc
  • Post about using AssemblyLoadContext to load plugins (code on github)
  • Post about using AssemblyLoadContext with a native library (code on github) (Disclaimer: mine)

这篇关于在加载上下文中加载非托管静态 dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆