如何使C(P /调用)code,从C#&QUOT调用;线程安全" [英] How to make C (P/invoke) code called from C# "Thread-safe"

查看:199
本文介绍了如何使C(P /调用)code,从C#&QUOT调用;线程安全"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些简单的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆