10 Stimmen

Wie man verriegelte Operationen gegen speicherabbildende Dateien in .Net verwendet

Gibt es eine Möglichkeit, die Interlocked.CompareExchange(); y Interlocked.Increment(); Methoden gegen Werte, die in einer Memory-Mapped-Datei gespeichert sind?

Ich möchte einen Multi-Thread-Dienst implementieren, der seine Daten in einer Memory-Mapped-Datei speichern wird, aber da es Multi-Thread ist, muss ich konfliktreiche Schreibvorgänge verhindern, daher wundere ich mich über die Interlocked-Operationen, anstatt explizite Sperren zu verwenden.

Ich weiß, dass es mit nativem Code möglich ist, aber kann es in verwaltetem Code auf .NET 4.0 getan werden?

7voto

TravisWhidden Punkte 2062

OK, so machen Sie es! Wir mussten das herausfinden, und ich dachte, wir könnten etwas an Stackoverflow zurückgeben!

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

Das funktioniert, und zwar über mehrere Prozesse hinweg! Ich freue mich immer über eine gute Herausforderung!

3voto

sinsalabim Punkte 41

TravisWhidden können Sie die Methode Interlocked.Increment Static wie folgt verwenden dan-gph sagte, müssen Sie nur vorsichtig sein mit Zeiger Casting und Operator Priorität, plus Klammern Verwendung, in Fakten ...

Sie wandeln einen Speicherzeiger (plus den gewünschten Offset) in einen Zeiger auf eine int-Variable um und verwenden diesen Zeiger dann als Variable. Dann müssen Sie ihn als Variablenreferenz verwenden.

Nachfolgend finden Sie das entsprechende Snippet von Ihnen, das die .net-Bibliothek anstelle des externen statischen Imports verwendet.

GEWINN- UND VERLUSTRECHNUNG

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X