共享文件锁

时间:2010-03-05 17:39:49

标签: file windows-services concurrency locking

我目前正在开发一个文件处理服务,该服务查看文件共享,其中文件通过FTP上传。

为了扩展性,我被要求使这项服务能够进行负载平衡,因此服务必须要求不同机器上的其他服务也可能尝试处理这些文件。

好的,所以我想我应该能够通过在处理文件之前获取我的进程的独占锁,并跳过可能已经被另一个进程锁定的任何文件来实现这一点。

这种方法的关键如下所示(为简单起见,我省略了错误处理):

using(FileStream fs = File.Open(myFile, FileMode.Open, FileAccess.ReadWrite, (FileShare.Read | FileShare.Delete))
{
//Do work
}

Q1:我的进程现在锁定了这个文件。我认为这意味着我可以访问相同的文件(不使用流)并仍然可以正确访问它,但基于测试,我似乎只有通过流锁定的好处。这是正确的吗?

(例如,在我包含FileShare.Delete,File.Delete(myFile)失败之前)

上述锁最终使用“写入”权限来确定哪个服务具有该文件,但是旨在允许其他进程仍然读取该文件。这是因为具有锁定的进程会尝试验证文件是否是有效的zip文件,该文件使用第三方库(Xceed.Zip)。但是,这说明文件“正被另一个进程”使用。使用反射器我最终发现有问题的呼叫是:

stream = this.m_info.Open(FileMode.Open, FileAccess.Read, FileShare.Read);

现在我希望这个能够工作,因为它只想读取文件,但它失败了。原因似乎在similar question中列出。但是,由于这是第三方API,我无法更改其代码以使用ReadWrite。

Q2:有没有办法可以正确锁定文件,以便其他服务无法获取,但仍然可以使用外部API验证为zip文件? < / p>

我觉得应该有一个'正确'的方法来做到这一点,但目前我能想到的最好的方法是锁定文件,将其从共享目录移开,然后在新的位置验证它位置。

1 个答案:

答案 0 :(得分:0)

如果您计划通过处理UnauthorizedAccessException来反应性地处理这种情况,我认为您犯了一个严重的错误。

这可以通过主动重命名文件来处理。例如,您可以将服务配置为仅读取名称格式为“Filename.YYYYMMDD.txt”的文件。在处理文件之前,您可以将其重命名为“Filename.YYYYMMDD.processing”。然后在处理完文件后,将其重命名为“Filename.YYYYMMDD.done”。

您甚至可以通过制作排列文件名的其他服务来更进一步。此服务将是一个FileSystemWatcher,用于侦听FileAdd操作。一旦收到该事件,它就会继续将Filename排队到全局消息队列。然后,您的每个服务都将出列文件名,不再需要担心并发访问。

HTH