如何使C(P /调用)代码从C#调用“线程安全”

前端之家收集整理的这篇文章主要介绍了如何使C(P /调用)代码从C#调用“线程安全”前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一些使用单个全局变量的简单的C代码.显然这不是线程安全的,所以当我使用P / invoke从C#中的多个线程中调用它时,事情就会变得困难.

如何为每个线程单独导入此函数,或使线程安全?

我尝试声明变量__declspec(线程),但这导致程序崩溃.我也尝试制作一个C/C++LI类,但它不允许成员函数为__declspec(裸),我需要(我正在使用inline-assembly).我编写多线程C代码并不是很有经验,所以可能有一些我错过的东西.

以下是一些示例代码

C#

  1. [DllImport("MyDll.dll",CallingConvention = CallingConvention.Cdecl)]
  2. public static extern int SomeFunction(int parameter1,int parameter2);

C

  1. extern "C"
  2. {
  3. int someGlobalVariable;
  4. int __declspec(naked) _someFunction(int parameter1,int parameter2)
  5. {
  6. __asm
  7. {
  8. //someGlobalVariable read/written here
  9. }
  10. }
  11. int __declspec(dllexport) SomeFunction(int parameter1,int parameter2)
  12. {
  13. return _someFunction(parameter1,parameter2);
  14. }
  15. }

[编辑]:SomeFunction()的结果必须按照一些规定的顺序,基于someGlobalVariable(例如,一个PRNG,一些GlobalVariable作为内部状态).所以,使用互斥体或其他类型的锁不是一个选项 – 每个线程必须有自己的someGlobalVariable的副本.

解决方法

一个常见的模式是拥有

>为状态分配内存的函数,
>一个没有副作用而是使传入状态变异的函数,
>一个释放状态的备忘录的功能.

C#端看起来像这样:

用法

  1. var state = new ThreadLocal<SomeSafeHandle>(NativeMethods.CreateSomeState);
  2.  
  3. Parallel.For(0,100,i =>
  4. {
  5. var result = NativeMethods.SomeFunction(state.Value,i,42);
  6.  
  7. Console.WriteLine(result);
  8. });

声明:

  1. internal static class NativeMethods
  2. {
  3. [DllImport("MyDll.dll",CallingConvention = CallingConvention.Cdecl)]
  4. public static extern SomeSafeHandle CreateSomeState();
  5.  
  6. [DllImport("MyDll.dll",CallingConvention = CallingConvention.Cdecl)]
  7. public static extern int SomeFunction(SomeSafeHandle handle,int parameter1,int parameter2);
  8.  
  9. [DllImport("MyDll.dll",CallingConvention = CallingConvention.Cdecl)]
  10. internal static extern int FreeSomeState(IntPtr handle);
  11. }

SafeHandle魔术:

  1. [SecurityPermission(SecurityAction.InheritanceDemand,UnmanagedCode = true)]
  2. [SecurityPermission(SecurityAction.Demand,UnmanagedCode = true)]
  3. internal class SomeSafeHandle : SafeHandle
  4. {
  5. [ReliabilityContract(Consistency.WillNotCorruptState,Cer.MayFail)]
  6. public SomeSafeHandle()
  7. : base(IntPtr.Zero,true)
  8. {
  9. }
  10.  
  11. public override bool IsInvalid
  12. {
  13. get { return this.handle == IntPtr.Zero; }
  14. }
  15.  
  16. [ReliabilityContract(Consistency.WillNotCorruptState,Cer.MayFail)]
  17. protected override bool ReleaseHandle()
  18. {
  19. return NativeMethods.FreeSomeState(this.handle) == 0;
  20. }
  21. }

猜你在找的C&C++相关文章