代码之家  ›  专栏  ›  技术社区  ›  MattH

共享文件锁定

  •  1
  • MattH  · 技术社区  · 15 年前

    我目前正在开发一个文件处理服务,它可以查看文件共享,文件通过ftp上传到其中。

    为了实现可伸缩性,我被要求使这个服务能够实现负载平衡,因此服务必须期望不同机器上的其他服务也可以尝试处理这些文件。

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

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

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

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

    (例如,在我包含fileshare.delete之前,file.delete(myfile)失败)

    上述锁最终使用“写”权限来确定哪个服务拥有该文件,但目的是允许其他进程仍然读取该文件。这是因为拥有锁的进程试图验证文件是否是有效的zip文件,该文件使用第三方库(xceed.zip)。但是这并不能说明文件 “正被其他进程使用” . 使用Reflector,我最终发现有问题的调用是:

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

    现在我本以为这会起作用,因为它只想读取文件,但失败了。原因似乎在 similar question . 但是,由于这是第三方API,我无法更改它们的代码以使用readwrite。

    问题2:是否有一种方法可以正确地锁定文件,使其不会被其他服务拾取,但它仍然可以使用外部API作为zip文件进行验证?

    我觉得应该有一种“正确”的方法来完成这项工作,但目前我能想到的最好方法是锁定文件,将其从共享目录中移出,然后在新的位置进行验证。

    1 回复  |  直到 15 年前
        1
  •  0
  •   jake.stateresa    15 年前

    如果你打算通过处理未经授权的访问异常来应对这种情况,我认为你犯了一个严重的错误。

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

    您甚至可以让另一个服务将文件名排队,从而使其更进一步。此服务将是一个文件系统监视程序,用于侦听fileadd操作。一旦它接收到该事件,就开始将文件名排队到全局消息队列。然后,您的每一个服务都只是将文件名排成队,不再需要担心并发访问。

    高温高压

    推荐文章