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 和 4 在这种情况下似乎最有可能(如果文件在另一个进程中打开,你会得到一个 IOException
)。
如果您想在同一台计算机上的多个客户端之间同步访问,您应该使用 Named Mutex。
我正在使用 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 和 4 在这种情况下似乎最有可能(如果文件在另一个进程中打开,你会得到一个 IOException
)。
如果您想在同一台计算机上的多个客户端之间同步访问,您应该使用 Named Mutex。