如何对.Net中的内存映射文件使用互锁操作

时间:2011-10-11 20:24:31

标签: .net-4.0 memory-mapped-files interlocked

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

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

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

2 个答案:

答案 0 :(得分:6)

好的,你就是这样做的!我们必须弄清楚这一点,我想我们可以回馈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)); 
    }
}

这确实有效,并且适用于多个流程!永远享受一个很好的挑战!

答案 1 :(得分:2)

TravisWhidden,实际上你可以使用Interlocked.Increment Static方法作为dan-gph说,你只需要注意指针转换和操作符优先级,加上括号用法,事实......

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

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

P&安培; l

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