该进程无法访问该文件,因为它正被另一个进程使用:正确读取\写入文件的方式:使用频繁的应用程序 - 第二部分

时间:2013-04-23 15:57:41

标签: c# asp.net .net

我们有一个使用频繁的.Net 3.5应用程序,它读取“创建昂贵的数据”并对其进行缓存。但是,我们在读取缓存文件和写入缓存文件时遇到很多错误。我从StackOverflow论坛获得的一些建议是:

  • 一个。在“FileShare.Read”模式下读取文件并写入文件 “FileShare.ReadWrite”模式。 (“FileAccess”模式应该是什么 在系统执行读/写操作时使用。)
  • 湾每次读取和写入操作后使用“GC.Collect”。(什么 是在每次之后这样做的性能影响 读/写操作。)

这是一种正确的读写文件的方法吗?请指教。

private XmlDocument ReadFromFile(string siteID, Type StuffType)
{
   XmlDocument result = null;
   var fsPath = FileSystemPath(siteID, StuffType.Name);
   result = new XmlDocument();
   using (var streamReader = new StreamReader(fsPath))
   //using (var fileStream = new FileStream(fsPath, FileMode.Open, FileAccess.Read, FileShare.Read))
   {
      result.Load(streamReader);
   }
   //GC.Collect();                
   return result;
}

private readonly object thisObject = new object();
private void WriteToFile(string siteID, XmlDocument stuff, string fileName)
{
   var fsPath = FileSystemPath(siteID, fileName);
   lock (thisObject)
   {
      //using (var fileStream = new FileStream(fsPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
      using (var streamWriter = new StreamWriter(fsPath))
      {
         stuff.Save(streamWriter);
      }
      //GC.Collect();
    }
 }

3 个答案:

答案 0 :(得分:7)

如果要同步访问资源,则有多个选项,具体取决于上下文。有几个(通用)情况:

  1. 单个流程,单线程

    无需同步。

  2. 单个进程,多个线程

    使用简单的锁定机制,例如lockReaderWriterLockSlim

  3. 多个进程,单机

    使用(命名)Mutex。互斥体不是很快。更多关于底层表现的信息。

  4. 多个进程,多台计算机

    现在它开始变得有趣了。 .NET没有针对此的现成解决方案。我可以想到两个解决方案:

    • try-again-method:在里面用try-catch创建一个while循环。让他在try-scope中进行资源操作。如果成功,则返回成功结果。如果失败,请等待几毫秒再试一次......再次......再次。
    • 同步主服务器:在网络中心位置运行Web服务。首先想要访问资源的所有进程都必须向服务请求权限。如果资源被“锁定”,则服务将等待,导致进程等待。一旦资源被释放,服务就会被通知,并允许下一个流程在线访问资源。
  5. 在这种情况下
    当然,最后一个解决方案是通用解决方案。对于Ajit Goel,它就像创建读/写文件的集中服务一样简单。然后你有一个文件管理员控制iets文件。

    另一种解决方案可能是将所有文件存储在中央数据库中,让他进行所有同步。

    <强>性能
    如果性能开始成为问题,您可以尝试创建缓存。

    1. 你可以在内存中创建一个缓存(但是有很多文件或大文件,这可能会成为内存问题)。
    2. 您可以在本地文件夹中创建缓存(每个进程一个)。只要修改了集中位置(只验证日期),就可以将该文件(带有Mutex锁)复制到您自己的本地文件夹中。从那里开始,您可以反复阅读文件而无需具有读取权限和读取共享的锁定。

答案 1 :(得分:1)

我认为将ReaderWriterLock与FileShare.ReadWrite结合使用是您的解决方案。 (注意,我链接到你的文档页面引用了一个名为ReaderWriterLockSlim的更好的版本,它应该至少同样好。)

每个线程都需要FileShare.ReadWrite,因此无论如何都可以访问它。每当线程需要阅读时,请将其AcquireReaderLock(以及读取完成时ReleaseReaderLock)。

如果你想写,只需使用UpgradeToWriterLock,完成后DowngradeFromWriterLock

这应该让所有线程始终以只读方式访问文件,并让任何一个线程在必要时获取写入权限。

希望有所帮助!

答案 2 :(得分:0)

我相信每个人都必须在FileShare.ReadWrite模式下打开文件。

如果有人在Fi​​leShare.Read模式下打开它,而其他人试图写入它,则会失败。我不认为它们兼容,因为有人说“只读共享”,但另一个想写。您可能需要在所有这些文件上使用FileShare.ReadWrite,或者最小化写入量以最小化冲突。

http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx

另一种选择是使用FileShare.Read,并在进行修改时复制文件。如果所有修改都有一个入口点,则可以使用FileShare.Read复制该文件。修改副本,然后更新某种指示当前文件路径的变量/属性。一旦更新,从文件读取的所有其他进程将使用该新位置。这将允许修改发生和完成,然后使所有读者都知道新修改的文​​件。同样,只有集中修改才有可行。如有必要,可能会通过某种修改请求队列。