我正在从客户端计算机复制到共享目录中的服务器计算机。我的服务器检测到新文件,复制完成后它必须处理它。问题是,当写入一个大文件并使用FileSystemWatcher
时,您没有得到复制是否完成的指示。检查这一点的唯一方法是尝试打开文件 ( File.OpenRead
/ OpenWrite
) 并获得异常。如何在不使用异常处理作为流控制的情况下获得副本已完成的通知?
我的第一个想法是如果我可以检测到用于写入文件的句柄何时关闭,我可以准确地知道复制何时完成,但我不知道该怎么做。
我正在从客户端计算机复制到共享目录中的服务器计算机。我的服务器检测到新文件,复制完成后它必须处理它。问题是,当写入一个大文件并使用FileSystemWatcher
时,您没有得到复制是否完成的指示。检查这一点的唯一方法是尝试打开文件 ( File.OpenRead
/ OpenWrite
) 并获得异常。如何在不使用异常处理作为流控制的情况下获得副本已完成的通知?
我的第一个想法是如果我可以检测到用于写入文件的句柄何时关闭,我可以准确地知道复制何时完成,但我不知道该怎么做。
您是否尝试过使用 FilesystemWatcher 和 Created 事件?
myWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Security | NotifyFilters.DirectoryName;
myWatcher.Created += new FileSystemEventHandler(watcher_Changed);
为什么客户端不能通过 WCF 服务调用(或其他方式)显式通知服务器,而不是使用这种轮询 FileSystemWatcher 的临时通知?您甚至可以制作一个客户端调用的简单 EXE NotifyServerFileUploaded.exe [name of file]
。
这样,就没有轮询,没有句柄诡计,也没有性能问题。
将文件复制到临时文件。复制完成后,重命名。重命名是原子的。只要确保服务器计算机忽略临时文件。
重试文件以进行独占读取。
int maxRetry = 3;
int x = 0;
tryAgain:
try
{
using (var fs = File.Open("file.txt", FileMode.Open,
FileAccess.Read,
FileShare.None))
{
// you have exclusive read here
}
}
catch (IOException)
{
if (x++ > maxRetry)
throw;
Thread.Sleep(500);
goto tryAgain;
}