【问题标题】:Load unmanaged static dll in load context在加载上下文中加载非托管静态 dll
【发布时间】:2017-03-27 14:36:49
【问题描述】:

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

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

如果我可以在某些情况下每次都加载 dll,然后调用 PInvoke,那么这个问题就会消失。

【问题讨论】:

  • AppDomains 只是窗口。由于 .net 核心在基于 Windows 和 unix 的系统上运行,因此您必须使用其他方式来加载非托管库(例如 PInvoke)
  • 您可以使用 PInvoke 加载非托管库。它适用于单声道,很可能适用于网络核心。例如,您可以查看我的旧问题:stackoverflow.com/questions/42977306/…
  • @IvanKishchenko,请查看已编辑的问题。
  • 修复原生库以允许多线程和/或多线程访问可能会更容易。
  • @omajid 库非常复杂,我无法查看源代码。还是谢谢。

标签: c# .net-core


【解决方案1】:

一种方法:

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

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

  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() 在加载上下文上的覆盖将被调用。

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

参考资料:

【讨论】:

    猜你喜欢
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2012-05-25
    相关资源
    最近更新 更多