2010-03-05 115 views
1

我目前工作的一个文件处理服务,着眼于文件共享,在文件通过FTP上传到。共享文件锁

在可扩展性,我被要求作出这项服务能够进行负载平衡,因此该服务有期待,在不同机器上的其他服务也可能试图处理这些文件。

OK,所以我想我应该能够处理文件之前得到我的过程中独占锁,并跳过可能已经被其他进程锁定任何文件实现这一目标。

这种方法的关键如下所示(我已经离开了错误处理的简单):

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

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

(例如,之前我包括FileShare.Delete,File.Delete(MYFILE)失败)

上面锁最终使用的“写入”权限,以确定哪些服务具有的文件,而是意在允许其他进程仍然读取文件。这是因为具有该锁的进程尝试验证该文件是否是使用第三方库(Xceed.Zip)的有效zip文件。但是,这没有说明文件“正在被另一个进程使用”。使用反射我终于找到了问题的电话是:

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

现在我本来期望这个工作,因为它只是想要阅读该文件,但它失败。原因似乎在similar question中概述。但是,由于这是第三方API,我无法将其代码更改为使用ReadWrite。

Q2:有没有一种方法可以正确锁定文件,使其不会被其他服务占用,但仍可以使用外部API将其验证为zip文件?

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

回答

0

如果你打算通过处理UnauthorizedAccessException我认为你正在犯一个严重的错误被动地处理这种情况。

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

你甚至可以把它更进一步,使该入队的另一名服务。该服务将是一个FileSystemWatcher,用于侦听FileAdd操作。一旦收到该事件,它就会将文件名排队到全局消息队列。然后,您的每个服务都将仅仅是取消文件名,而不再需要担心并发访问。

HTH

+0

接受为替代解决方案是合理的。回答我自己的问题: 问题1:是的。锁仅用于流,而不是流程 Q2:否。必须考虑替代方案。 – MattH 2010-04-23 10:39:46