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

时间:2017-03-27 14:36:50

标签: c# .net-core

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

修改 目前使用PInvoke调用代码并且工作正常。问题是因为这个unmanged dll的性质,当我尝试并行调用它时抛出AccessViolationException,因为两个或更多任务想要访问相同的内存。

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

1 个答案:

答案 0 :(得分:3)

一种方法:

  1. headers = ['APPL', 'Std_1', 'Std_2', 'Std_3', 'Mean'] values = [['ACCMGR', 106.8754, 130.1600, 107.1861, 114.750510], ['ACCOUNTS', 121.7034, 113.4927, 114.5482, 116.581458], ['AUTH', 116.8585, 112.4487, 115.2700, 114.859050]] df = pd.DataFrame(values, columns=headers) df.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 3 entries, 0 to 2 Data columns (total 5 columns): APPL 3 non-null object Std_1 3 non-null float64 Std_2 3 non-null float64 Std_3 3 non-null float64 Mean 3 non-null float64 dtypes: float64(4), object(1) memory usage: 200.0+ bytes def make_count(comp_cols, mean_col): count_d = {'greater': 0, 'less': 0} for col in comp_cols: if col > mean_col: count_d['greater'] += 1 elif col < mean_col: count_d['less'] += 1 return count_d['greater'], count_d['less'], (count_d['greater'] + count_d['less']) def apply_make_count(df): a, b, c = df.apply(lambda row: make_count([row['Std_1'], row['Std_2'], row['Std_3']], row['Mean']), axis=1) df['greater'], df['less'], df['count'] = list(zip(a, b, c)) apply_make_count(df) df = APPL Std_1 Std_2 Std_3 Mean greater less count 0 ACCMGR 106.8754 130.1600 107.1861 114.750510 1 2 3 1 ACCOUNTS 121.7034 113.4927 114.5482 116.581458 1 2 3 2 AUTH 116.8585 112.4487 115.2700 114.859050 2 1 3 派生课程
  2. 在默认上下文中覆盖System.Runtime.Loader.AssemblyLoadContext并调用Load(AssemblyName assemblyName)或将null返回到后备状态
  3. 覆盖LoadFromAssemblyPath()并调用IntPtr LoadUnmanagedDll(string unmanagedDllName)以加载您的本机dll
  4. 通过某些已知的LoadUnmanagedDllFromPath()间接访问您的pinvoke方法并加载本机/非托管库

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

  1. 通话代码
  2. Pinvoke代码
  3. 前两个共享的界面

在调用代码中:

interface

var assem = assemblyLoadContext.LoadFromAssemblyName(new System.Reflection.AssemblyName(pinvokeAssemblyName)); var type = assem.GetType(nameOfTypeThatCallsPinvoke); return (ISharedInterface)Activator.CreateInstance(type); 实例尝试使用pinvoke方法时,将调用您在加载上下文上的nameOfTypeThatCallsPinvoke覆盖。

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

参考文献: