有没有办法对存储在内存映射文件中的值使用Interlocked.CompareExchange();
and方法?Interlocked.Increment();
我想实现一个多线程服务,它将其数据存储在内存映射文件中,但由于它是多线程的,我需要防止写入冲突,因此我想知道互锁操作而不是使用显式锁。
我知道可以使用本机代码,但是可以在 .NET 4.0 上的托管代码中完成吗?
有没有办法对存储在内存映射文件中的值使用Interlocked.CompareExchange();
and方法?Interlocked.Increment();
我想实现一个多线程服务,它将其数据存储在内存映射文件中,但由于它是多线程的,我需要防止写入冲突,因此我想知道互锁操作而不是使用显式锁。
我知道可以使用本机代码,但是可以在 .NET 4.0 上的托管代码中完成吗?
好的,这就是你的做法!我们必须弄清楚这一点,我认为我们可以回馈给 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));
}
}
这确实有效,并且可以跨多个进程工作!永远享受一个好的挑战!
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)))
}
}
}