我有一个Web服务来处理Excel文件(以前上传到服务器),这涉及大量的数据库更新,并且需要很长时间。我想提供另一个可以调用的Web服务来检查此过程的进度。它将进程的ID(可能是GUID)作为输入并返回int
(0-100)表示进度。
我的想法是,长时间运行的服务可能会创建仅内存MemoryMappedFile
(MMF) - 仅需sizeof(int)
个字节 - 它会在某个时间间隔内报告其进度。 "进展"然后,服务可以打开MMF,阅读int
,然后向主叫方报告。
我有两个问题。首先,我对MMF没有多少经验,所以我可能没有意识到这里有一些陷阱吗?其次,更重要的是,在这种情况下是否需要同步,因为只有一个写入者?经过一番搜索,我无法发现MemoryMappedViewAccessor.Write
是int
的原子。
答案 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。根据您的描述,您可以在报告进度的服务中静态存储(可能在并发集合中)进度。您可以通过仅暴露另一个端点或方法来解决此问题,第二个服务可以调用该端点或方法来更新特定客户端/文件的进度。完成后,它只是告诉它将其从内存中删除。