如何使C(P /调用)code,从C#&QUOT调用;线程安全" [英] How to make C (P/invoke) code called from C# "Thread-safe"
问题描述
我有一些简单的C code,它使用一个全局变量。显然,这不是线程安全的,所以当我使用P / Invoke在C#中调用它从多个线程,事情搞砸了。
I have some simple C-code which uses a single global-variable. Obviously this is not thread-safe, so when I call it from multiple threads in C# using P/invoke, things screw up.
如何可以我要么导入该功能分别为每个线程,或使其线程安全的?
我试过声明变量 __ declspec(线程)
,但导致程序崩溃。我也试着做一个C ++ / CLI类,但它不允许成员函数是 __ declspec(裸)
,这是我需要的(我使用内联汇编)的。我不是很有经验编写多线程C ++ code,所以有可能是我丢失的东西。
I tried declaring the variable __declspec(thread)
, but that caused the program to crash. I also tried making a C++/CLI class, but it doesn't allow member-functions to be __declspec(naked)
, which I need (I'm using inline-assembly). I'm not very experienced writing multi-threaded C++ code, so there might be something I'm missing.
下面是一些例子code:
Here is some example code:
C#
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SomeFunction(int parameter1, int parameter2);
C ++
extern "C"
{
int someGlobalVariable;
int __declspec(naked) _someFunction(int parameter1, int parameter2)
{
__asm
{
//someGlobalVariable read/written here
}
}
int __declspec(dllexport) SomeFunction(int parameter1, int parameter2)
{
return _someFunction(parameter1, parameter2);
}
}
:结果 SomeFunction()
必须基于一些prescribed秩序someGlobalVariable
的(想想如的。一个PRNG,与 someGlobalVariable
作为内部状态)的。因此,使用互斥体或其他类型的锁是不是一种选择 - 每个线程的必须的有它自己的拷贝 someGlobalVariable
: The result of SomeFunction()
must go in some prescribed order based on someGlobalVariable
(think of eg. a PRNG, with someGlobalVariable
as the internal state). So, using a mutex or other sort of lock is not an option - each thread must have its own copy of someGlobalVariable
.
推荐答案
一个常见的模式是有
A common pattern is to have
- 对于国家分配内存功能,
- 有没有副作用,但功能突变传入的状态,
- ,释放为国家memoy的功能。
C#的一面是这样的:
The C# side would look like this:
的用法:的
var state = new ThreadLocal<SomeSafeHandle>(NativeMethods.CreateSomeState);
Parallel.For(0, 100, i =>
{
var result = NativeMethods.SomeFunction(state.Value, i, 42);
Console.WriteLine(result);
});
的声明:的
internal static class NativeMethods
{
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern SomeSafeHandle CreateSomeState();
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SomeFunction(SomeSafeHandle handle,
int parameter1,
int parameter2);
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int FreeSomeState(IntPtr handle);
}
的的SafeHandle法宝:的
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class SomeSafeHandle : SafeHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public SomeSafeHandle()
: base(IntPtr.Zero, true)
{
}
public override bool IsInvalid
{
get { return this.handle == IntPtr.Zero; }
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return NativeMethods.FreeSomeState(this.handle) == 0;
}
}
这篇关于如何使C(P /调用)code,从C#&QUOT调用;线程安全&QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!