加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 05:31:15 所属栏目:百科 来源:网络整理
导读:我有一些使用单个全局变量的简单的C代码.显然这不是线程安全的,所以当我使用P / invoke从C#中的多个线程中调用它时,事情就会变得困难. 如何为每个线程单独导入此函数,或使线程安全? 我尝试声明变量__declspec(线程),但这导致程序崩溃.我也尝试制作一个C/C++
我有一些使用单个全局变量的简单的C代码.显然这不是线程安全的,所以当我使用P / invoke从C#中的多个线程中调用它时,事情就会变得困难.

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

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

以下是一些示例代码:

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

解决方法

一个常见的模式是拥有

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

C#端看起来像这样:

用法:

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;
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读