我们有一个使用频繁的.Net 3.5应用程序,它读取“创建昂贵的数据”并对其进行缓存。但是,我们在读取缓存文件和写入缓存文件时遇到很多错误。我从StackOverflow论坛获得的一些建议是:
这是一种正确的读写文件的方法吗?请指教。
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();
}
}
答案 0 :(得分:7)
如果要同步访问资源,则有多个选项,具体取决于上下文。有几个(通用)情况:
单个流程,单线程
无需同步。
单个进程,多个线程
使用简单的锁定机制,例如lock
或ReaderWriterLockSlim
。
多个进程,单机
使用(命名)Mutex
。互斥体不是很快。更多关于底层表现的信息。
多个进程,多台计算机
现在它开始变得有趣了。 .NET没有针对此的现成解决方案。我可以想到两个解决方案:
在这种情况下
当然,最后一个解决方案是通用解决方案。对于Ajit Goel,它就像创建读/写文件的集中服务一样简单。然后你有一个文件管理员控制iets文件。
另一种解决方案可能是将所有文件存储在中央数据库中,让他进行所有同步。
<强>性能强>
如果性能开始成为问题,您可以尝试创建缓存。
答案 1 :(得分:1)
我认为将ReaderWriterLock与FileShare.ReadWrite结合使用是您的解决方案。 (注意,我链接到你的文档页面引用了一个名为ReaderWriterLockSlim的更好的版本,它应该至少同样好。)
每个线程都需要FileShare.ReadWrite,因此无论如何都可以访问它。每当线程需要阅读时,请将其AcquireReaderLock
(以及读取完成时ReleaseReaderLock
)。
如果你想写,只需使用UpgradeToWriterLock
,完成后DowngradeFromWriterLock
。
这应该让所有线程始终以只读方式访问文件,并让任何一个线程在必要时获取写入权限。
希望有所帮助!
答案 2 :(得分:0)
我相信每个人都必须在FileShare.ReadWrite模式下打开文件。
如果有人在FileShare.Read模式下打开它,而其他人试图写入它,则会失败。我不认为它们兼容,因为有人说“只读共享”,但另一个想写。您可能需要在所有这些文件上使用FileShare.ReadWrite,或者最小化写入量以最小化冲突。
http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx
另一种选择是使用FileShare.Read,并在进行修改时复制文件。如果所有修改都有一个入口点,则可以使用FileShare.Read复制该文件。修改副本,然后更新某种指示当前文件路径的变量/属性。一旦更新,从文件读取的所有其他进程将使用该新位置。这将允许修改发生和完成,然后使所有读者都知道新修改的文件。同样,只有集中修改才有可行。如有必要,可能会通过某种修改请求队列。