有没有办法对存储在内存映射文件中的值使用Interlocked.CompareExchange();
和Interlocked.Increment();
方法?
我想实现一个多线程服务,将其数据存储在内存映射文件中,但由于它是多线程的,我需要防止冲突写入,因此我想知道Interlocked操作而不是使用显式锁。
我知道可以使用本机代码,但可以在.NET 4.0上的托管代码中完成吗?
答案 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)))
}
}
}