在加载上下文中加载非托管静态dll [英] Load unmanaged static dll in load context
问题描述
我有本地非托管dll,它是静态的,如果我想并行运行它,则每次需要库执行某些工作时都必须加载该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()
加载本地dll - 通过某些已知的
接口
- 调用代码
- Pinvoke代码
- 前两个共享的接口
- AssemblyLoadContext设计文档
- 有关使用AssemblyLoadContext加载插件的帖子( github上的代码)
- 关于将AssemblyLoadContext与本机库一起使用的帖子( github上的代码)(免责声明:我的)
- Derive class from
System.Runtime.Loader.AssemblyLoadContext
- Override
Load(AssemblyName assemblyName)
callingLoadFromAssemblyPath()
or returning null to fallback on default context - Override
IntPtr LoadUnmanagedDll(string unmanagedDllName)
callingLoadUnmanagedDllFromPath()
to load your native dll - Indirectly access your pinvoke methods and load the native/unmanaged library through some known
interface
- Calling code
- Pinvoke code
- Interfaces shared by the first two
- 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)
间接访问您的pinvoke方法并加载本机/非托管库。 ol>
第4步是您需要根据结构进行调整的部分现有代码。就我而言,我创建了3个程序集:
在调用代码中:
var assem = assemblyLoadContext.LoadFromAssemblyName(new
System.Reflection.AssemblyName(pinvokeAssemblyName));
var type = assem.GetType(nameOfTypeThatCallsPinvoke);
return(ISharedInterface)Activator.CreateInstance(type);
当 nameOfTypeThatCallsPinvoke实例
尝试使用pinvoke时方法,您的 LoadUnmanagedDll()
在加载上下文中的覆盖将被调用。
需要共享接口,因此类型为在编译时已知。如果调用代码直接引用了pinvoke库,则其类型将不同于通过加载上下文获得的类型。
参考文献:
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?
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.
If I could load dll for each time that in some context and then call PInvoke on that this problem would be gone.
One approach:
Step 4 is the part you need to adjust based on the structure of the existing code. In my case, I created 3 assemblies:
In the calling code:
var assem = assemblyLoadContext.LoadFromAssemblyName(new
System.Reflection.AssemblyName(pinvokeAssemblyName));
var type = assem.GetType(nameOfTypeThatCallsPinvoke);
return (ISharedInterface)Activator.CreateInstance(type);
When instance of nameOfTypeThatCallsPinvoke
attempts to use pinvoke method your LoadUnmanagedDll()
override on the load context will get called.
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.
References:
这篇关于在加载上下文中加载非托管静态dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!