How to use interlocked operations against memory-mapped files in .Net

老子叫甜甜 提交于 2019-11-29 09:23:43

问题


Is there any way to use the Interlocked.CompareExchange(); and Interlocked.Increment(); methods against values stored in a memory-mapped file?

I'd like to implement a multi-threaded service that will store its data in a memory-mapped file, but since it's multi-threaded I need to prevent conflicting writes, therefore I wonder about the Interlocked operations rather than using explicit locks.

I know it's possible with native code, but can it be done in managed code on .NET 4.0?


回答1:


OK, this is how you do it! We had to figure this out, and I figured we could give some back to 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)); 
    }
}

This does work, and works across multiple processes! Always enjoy a good challenge!




回答2:


TravisWhidden, actually you can use Interlocked.Increment Static method as dan-gph said, you just have to be careful with pointer casting and operator priority, plus parenthesis usage, in facts...

You'll cast a memory pointer (plus the desired offset), into a pointer to an int variable, then you'll use that pointer as a variable. Then you'll have to use it as a variable reference.

Below you'll find the corresponding snippet of yours using .net library instead of external static import.

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


来源:https://stackoverflow.com/questions/7732042/how-to-use-interlocked-operations-against-memory-mapped-files-in-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!