1

我们有一个大量使用的 .Net 3.5 应用程序,它读取“创建成本高”的数据并将其缓存。但是,我们在读取缓存文件和写入缓存文件时遇到了很多错误。我从 StackOverflow 论坛得到的一些建议是:

  • 一个。以“FileShare.Read”模式读取文件并以“FileShare.ReadWrite”模式写入文件。(系统在进行读\写操作时应该使用什么“文件访问”模式。)
  • 湾。在每次读写操作后使用“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();
    }
 }
4

3 回答 3

7

如果您想同步对资源的访问,有几个选项,具体取决于上下文。有几种(一般)情况:

  1. 单进程,单线程

    无需同步。

  2. 单进程,多线程

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

  3. 多工序,单机

    使用 (命名) Mutex。互斥锁不是很快。更多关于底部的性能。

  4. 多进程,多台机器

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

    • try-again-method:创建一个带有 try-catch 的 while 循环。让他做try-scope中的资源操作。如果成功,则返回成功结果。如果失败,请等待几毫秒,然后再试一次……再试一次……再试一次。
    • 同步主机:使 web 服务在网络的中心位置运行。所有想要访问资源的进程首先必须向服务请求许可。如果资源被“锁定”,服务将等待,导致进程等待。一旦资源被释放,服务就会被通知并允许下一个进程访问该资源。

在这种情况下
,当然最后一个解决方案是通用解决方案。在 Ajit Goel 的情况下,它就像创建一个集中式服务来读/写文件一样简单。然后你有一个文件管理员可以控制 iets 文件。

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

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

  1. 您可以在内存中创建缓存(但有很多文件或大文件,这可能会成为内存问题)。
  2. 您可以在本地文件夹中创建一个缓存(每个进程一个)。一旦修改了集中位置(只需验证日期),您就可以将该文件(使用互斥锁)复制到您自己的本地文件夹中。在那里,您可以一遍又一遍地读取文件,而无需锁定读取访问和读取共享。
于 2013-04-23T16:14:43.160 回答
1

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

您需要在每个线程上使用 FileShare.ReadWrite,因此他们都可以根据需要访问它。任何时候线程需要读取,都拥有它AcquireReaderLock(以及ReleaseReaderLock读取完成时)。

当你想写时,只需使用UpgradeToWriterLock,当你完成时,DowngradeFromWriterLock

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

希望有帮助!

于 2013-04-23T16:22:28.850 回答
0

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

如果有人在 FileShare.Read 模式下打开它,而其他人试图写入它,它将失败。我认为它们不兼容,因为一个说“只读共享”,但另一个想写。您可能需要在所有这些上使用 FileShare.ReadWrite,或者尽量减少写入量以最大限度地减少冲突。

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

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

于 2013-04-23T16:08:35.500 回答