none
内存映射文件 RRS feed

  • 问题

  •     某个第三方应用程序间隔大概3秒左右会更新某个磁盘上的文件,现对那个文件,我在我写的c#程序中创建了内存映射文件方式间隔1分钟左右进行只读这个内存映射视图。 开头几分钟内读取这个文件和别人软件写入这个文件都不会明显影响,后面就发觉是不是内存映射文件的同时造成了 这个文件加锁导致第三方应用程序无法及时将数据更新到文件里面去。。

    原想间隔2秒将这个文件拷贝到磁盘另外一个位置再进行读取。但考虑硬盘的最大速度限制,这个方案无法满足。上面提到的就是  文件的快速读取不会给别人造成死锁或类似ms-sql不管脏数据还是正确的数据都可以不影响另外程序的写入更新 来直接 读取。。。

    string shFilePath=@"c:\a.data";

       FileStream fs = new FileStream(shFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                             
                               //采用随机访问定义(采用这个方法创建,程序马上提示文件被占用异常)
                              //shmemoryFile=MemoryMappedFile.CreateFromFile(shFilePath, FileMode.Open, Const.SH_SHAREDMEMORYMAPPEDFILESHMINUTEQUOTES, fs.Length, MemoryMappedFileAccess.Read);

                               //采用持久访问定义
                               shmemoryFile = MemoryMappedFile.CreateFromFile(fs, Const.SH_SHAREDMEMORYMAPPEDFILESHMINUTEQUOTES, fs.Length, MemoryMappedFileAccess.Read, null, HandleInheritability.None, false);
                               shaccessor = shmemoryFile.CreateViewAccessor(0, fs.Length, MemoryMappedFileAccess.Read);
                                fs.Close();
                                fs.Dispose();

    2011年1月11日 7:06

答案

  • 您好,天草麟:

    欢迎来到MSDN论坛。对于您的问题,我认为在读取这个文件的时候,最好能采用LOCK来锁定对象操作。 正如您之前描述过的,大智慧在2-3秒内就要更新2-3千条数据,您是否能保证,当您在做内存映射的同时,大智慧正在重新写入数据呢。我建议您看看下面的例子,或许对您解决这个问题能够提供帮助:

    A C# Framework for Interprocess Synchronization and Communication:
    http://www.codeproject.com/KB/threads/csthreadmsg.aspx

    感谢您的参与,如果您还有如何其他问题,请随时告知我们。


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the C# Forum! If you have any feedback, please tell us.
    • 已标记为答案 天草麟 2011年1月18日 9:54
    2011年1月17日 4:57

全部回复

  • 那个 FileStream 已经把文件打开了,在创建随机的内存映射文件会导致异常。其实我看到您之所以用 FileStream 就是希望得到这个文件的原始数据长度,您可以换一种方法获得这个值,或者一旦获得了长度就先关闭那个 FileStream 再创建内存映射。
    Mark Zhou
    2011年1月11日 9:29
  • 那个 FileStream 已经把文件打开了,在创建随机的内存映射文件会导致异常。其实我看到您之所以用 FileStream 就是希望得到这个文件的原始数据长度,您可以换一种方法获得这个值,或者一旦获得了长度就先关闭那个 FileStream 再创建内存映射。
    Mark Zhou

    恩,但我想 内存映射文件  应该来说只有创建一次,在创建过程中我利用FileStream来获取长度,并在 CreateFromFile方法的最后一个参数指定False 进行自动关闭FileStream应该来说不会影响。

    我最想问各位大牛的是:为什么再创建内存映射文件后,反复间隔比如2秒读取这个内存映射视图一段时间后,第三方程序写入的速度为什么开始延迟很厉害?是因为文件视图给人家锁死造成其他程序不能及时更新这个文件还是?

    2011年1月11日 10:06
  •  FileStream fs = new FileStream(shFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                                long  length = fs.Length;
                                fs.Close();
                                fs.Dispose();
                                //非持久内存映射文件
                                //shmemoryFile = MemoryMappedFile.CreateNew(shFilePath, fs.Length, MemoryMappedFileAccess.Read, MemoryMappedFileOptions.None, null, HandleInheritability.None);//这个地方马上抛出  文件已被另外一个进程占用,无法打开异常,但使用FileStream却很正常
                                   
                                shmemoryFile = MemoryMappedFile.CreateFromFile(shFilePath, FileMode.Open, Const.SH_SHAREDMEMORYMAPPEDFILESHMINUTEQUOTES, length,MemoryMappedFileAccess.ReadWrite);    
    2011年1月12日 2:54
  • 应该不是 MappedFile 本身的问题。它就是 Windows 的一个 Kernel Object 的 .NET 实现。所以功能和 Windows 的一模一样。

    我觉得问题可能在于那个 MemoryMappedFile 在创建时有缓冲区模式,可能是由于频繁操作缓存导致其产生大量的 Event 或者 Spin 锁,我等会写个程序跑跑看看有没有这个问题。

    程序每次写数据大概有多大?


    Mark Zhou
    2011年1月12日 8:40
  • 这个数据文件是大智慧的分笔数据文件,更新频率非常频繁约2、3秒会更新。写入数据大约有每次近千条数据。
    2011年1月13日 0:51
  • 我回去有空写个 Demo 试试看,模拟一下,1,000 条数据,每隔 2 秒。有结果了我再更新您。
    Mark Zhou
    2011年1月13日 9:46
  • 恩,非常的感谢 mazhou
    2011年1月14日 0:40
  • 您好,天草麟:

    欢迎来到MSDN论坛。对于您的问题,我认为在读取这个文件的时候,最好能采用LOCK来锁定对象操作。 正如您之前描述过的,大智慧在2-3秒内就要更新2-3千条数据,您是否能保证,当您在做内存映射的同时,大智慧正在重新写入数据呢。我建议您看看下面的例子,或许对您解决这个问题能够提供帮助:

    A C# Framework for Interprocess Synchronization and Communication:
    http://www.codeproject.com/KB/threads/csthreadmsg.aspx

    感谢您的参与,如果您还有如何其他问题,请随时告知我们。


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Welcome to the C# Forum! If you have any feedback, please tell us.
    • 已标记为答案 天草麟 2011年1月18日 9:54
    2011年1月17日 4:57