c# FileSystemWatcher 在多个客户端上触发

c# FileSystemWatcher fires on multiple clients

我正在使用 FileSystemWatcher 观看目录。我创建了一个 _Created() 事件处理程序,以便在将文件移动到此文件夹时触发。我的问题如下:

当用户点击 "real life button"(我们库存中的按钮,而不是应用程序中的按钮)时,将创建此目录中的文件。 FileSystemWatcher 拿走这个文件,在系统中做一些事情然后删除它。当应用程序只运行一次时,这不是问题。但它被6个客户使用。所以每个客户端上的每个应用程序都试图删除它。如果一个客户端太慢,它会抛出异常,因为文件已经被删除了。

我想问的是:有没有办法避免这种情况?

我尝试使用循环检查文件是否仍然存在,但没有成功。

while (File.Exists(file))
{
    File.Delete(file);
    Thread.Sleep(100);
}

谁能告诉我它可能如何工作?

设计

如果您希望一个文件仅由单个实例处理(例如,第一个做出反应的实例获得工作),那么您应该实施锁定机制。只有能够获得文件锁的实例才允许处理和删除它,所有其他实例应跳过该文件。

如果您对处理文件的所有实例都满意,并且只关心其中至少一个成功,那么您需要弄清楚哪些异常表示真正的失败,哪些表示由操作引起的失败另一个例子。

锁定

要'lock'一个文件,你可以用共享模式打开它FileShare.None。这可以防止其他进程打开它,直到您关闭该文件。但是,您随后需要先关闭该文件,然后才能删除它,这会留下一个小间隙,在此期间另一个实例可以打开该文件。

更好的解决方案是为此创建一个单独的锁定文件。使用 file-mode FileMode.Create 和 share-mode FileShare.None 创建它并保持打开状态直到整个过程完成,包括删除已处理的文件。然后可以关闭锁定文件并有选择地删除它。

异常

至于 UnauthorizedAccessException,根据 documentation,这意味着以下 4 种情况之一:

  1. 您没有所需的权限
  2. 该文件是正在使用的可执行文件
  3. 路径为目录
  4. 该文件是只读的

1 和 4 在这种情况下似乎最有可能(如果文件在另一个进程中打开,你会得到一个 IOException)。

如果您想在同一台计算机上的多个客户端之间同步访问,您应该使用 Named Mutex