具有单个编写器的MemoryMappedFile是否需要同步

时间:2014-08-01 16:16:24

标签: c# web-services synchronization memory-mapped-files

我有一个Web服务来处理Excel文件(以前上传到服务器),这涉及大量的数据库更新,并且需要很长时间。我想提供另一个可以调用的Web服务来检查此过程的进度。它将进程的ID(可能是GUID)作为输入并返回int(0-100)表示进度。

我的想法是,长时间运行的服务可能会创建仅内存MemoryMappedFile(MMF) - 仅需sizeof(int)个字节 - 它会在某个时间间隔内报告其进度。 "进展"然后,服务可以打开MMF,阅读int,然后向主叫方报告。

我有两个问题。首先,我对MMF没有多少经验,所以我可能没有意识到这里有一些陷阱吗?其次,更重要的是,在这种情况下是否需要同步,因为只有一个写入者?经过一番搜索,我无法发现MemoryMappedViewAccessor.Writeint的原子。

1 个答案:

答案 0 :(得分:0)

我之前并不确定,因为之前我没有使用过MMF,但我现在使用the samples on MSDN进行了测试。

简短的回答是否定,不需要同步(如果你考虑它,这是有道理的)。您有以下两个示例 - 编写器进程和读取器进程,作为控制台应用程序。

唯一的问题是,您希望在每次读取/写入后将写入/读取流中的光标位置重置为0,或者为前32位创建视图映射。不确定第二个是否有效(很可能没有,你仍然需要重置文件指针)。

作家流程:

    static void Main(string[] args)
    {
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))
        {
            int i = 0;
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    while (i++ < 10000)
                    {
                        writer.Write(i);
                        Thread.Sleep(50);
                        writer.Seek(0, SeekOrigin.Begin);
                    }
                }
            }

            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }

读者流程:

    static void Main(string[] args)
    {
        try
        {
            using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
            {
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    using (BinaryReader reader = new BinaryReader(stream))
                    {
                        int value = 0;
                        while (value != 10000)
                        {
                            value = reader.ReadInt32();
                            Console.WriteLine("Process A says: {0}", value);
                            stream.Seek(0L, SeekOrigin.Begin);
                            Thread.Sleep(20);
                        }
                    }
                }
            }
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("Memory-mapped file does not exist. Run Process A first.");
        }
    }

我故意让读者在读取之间等待,而不是作者在写入之间等待,以确保没有巧合。

输出符合预期,但不等待它完成:

Process A says: 85
Process A says: 85
Process A says: 85
Process A says: 86
Process A says: 86
Process A says: 87
Process A says: 87
Process A says: 87
Process A says: 88
Process A says: 88
Process A says: 89
Process A says: 89
Process A says: 89
Process A says: 90
Process A says: 90
Process A says: 91
Process A says: 91
Process A says: 91
Process A says: 92
Process A says: 92
Process A says: 93
Process A says: 93
Process A says: 93
Process A says: 94

话虽如此,我仍然不推荐MMF。根据您的描述,您可以在报告进度的服务中静态存储(可能在并发集合中)进度。您可以通过仅暴露另一个端点或方法来解决此问题,第二个服务可以调用该端点或方法来更新特定客户端/文件的进度。完成后,它只是告诉它将其从内存中删除。