9

有没有办法对存储在内存映射文件中的值使用Interlocked.CompareExchange();and方法?Interlocked.Increment();

我想实现一个多线程服务,它将其数据存储在内存映射文件中,但由于它是多线程的,我需要防止写入冲突,因此我想知道互锁操作而不是使用显式锁。

我知道可以使用本机代码,但是可以在 .NET 4.0 上的托管代码中完成吗?

4

2 回答 2

7

好的,这就是你的做法!我们必须弄清楚这一点,我认为我们可以回馈给 stackoverflow!

class Program
{

    internal static class Win32Stuff
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        unsafe public static extern int InterlockedIncrement(int* lpAddend);
    }

    private static MemoryMappedFile _mmf;
    private static MemoryMappedViewStream _mmvs;

    unsafe static void Main(string[] args)
    {
        const int INT_OFFSET = 8;

        _mmf = MemoryMappedFile.CreateOrOpen("SomeName", 1024);

        // start at offset 8 (just for example)
        _mmvs = _mmf.CreateViewStream(INT_OFFSET, 4); 

        // Gets the pointer to the MMF - we dont have to worry about it moving because its in shared memory
        var ptr = _mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle(); 

        // Its important to add the increment, because even though the view says it starts at an offset of 8, we found its actually the entire memory mapped file
        var result = Win32Stuff.InterlockedIncrement((int*)(ptr + INT_OFFSET)); 
    }
}

这确实有效,并且可以跨多个进程工作!永远享受一个好的挑战!

于 2012-08-24T20:54:47.633 回答
3

TravisWhidden,实际上你可以使用dan-gph所说的 Interlocked.Increment Static 方法,你只需要小心指针转换和运算符优先级,加上括号的使用,事实上......

您将内存指针(加上所需的偏移量)转换为指向 int 变量的指针,然后将该指针用作变量。然后,您必须将其用作变量引用。

您将在下面找到使用 .net 库而不是外部静态导入的相应片段。

损益

class Program
{
    private static MemoryMappedFile _mmf;
    private static MemoryMappedViewStream _mmvs;

    static void Main(string[] args)
    {
        const int INT_OFFSET = 8;

        _mmf = MemoryMappedFile.CreateOrOpen("SomeName", 1024);
        _mmvs = _mmf.CreateViewStream(INT_OFFSET, 4); 

        unsafe
        {
            IntPtr ptr = _mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle();
            Interlocked.Increment(ref (*((int*)(ptr + INT_OFFSET)))
        }
    }
}
于 2018-06-04T10:12:28.837 回答