我设置了一个文件系统观察程序来处理/移动转储到某个位置的文件。我运行它的前几次,它运行良好,然后随机停止检测文件更改。什么可能导致这个?我将在下面发布我的代码。
protected override void OnStart(string[] args)
{
fileSystemWatcher1.Path = Config.ToString("WATCHPATH");
//ignore subfolder changes (error and archive)
fileSystemWatcher1.IncludeSubdirectories = false;
//add event handlers
fileSystemWatcher1.Changed += new FileSystemEventHandler(OnChanged);
fileSystemWatcher1.Created += new FileSystemEventHandler(OnChanged);
fileSystemWatcher1.Deleted += new FileSystemEventHandler(OnDeleted);
fileSystemWatcher1.Renamed += new RenamedEventHandler(OnRenamed);
//begin watching
fileSystemWatcher1.EnableRaisingEvents = true;
}
void OnChanged(object sender, FileSystemEventArgs e)
{
try
{
FileAttributes attr;
try
{
attr = File.GetAttributes(e.FullPath);
}
catch (FileNotFoundException fnfEx)
{
//this is here because after you move the file to the archive folder
//it triggers a change, and can't find the old file. This ignores changes
//in subdirectories after moves from main drop folder
return;
}
//this checks if a path is a directory which eliminates circular events being triggered
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
return;
}
FileProcessor fp = new FileProcessor();
fp.Process(e.FullPath);
DirectoryInfo parentDirectory = System.IO.Directory.GetParent(e.FullPath);
string archivePath = parentDirectory.FullName + "\\Archive\\" + Settings._sys.User.UserID + "_" + DateTime.Today.Date.ToString("ddMMMMyyyy") + "_" + e.Name;
if (!Directory.Exists(parentDirectory.FullName + "\\Archive"))
{
//create archive directory
Directory.CreateDirectory(parentDirectory.FullName + "\\Archive");
}
//appends number to file if the filename already exists
if (File.Exists(archivePath))
{
string pathOnly = archivePath.Substring(0, archivePath.LastIndexOf('\\'));
string[] files = Directory.GetFiles(pathOnly, Path.GetFileNameWithoutExtension(archivePath) + "*" + Path.GetExtension(archivePath));
int x = files.Max(f => GetFileNumber(f)) + 1;
string fileNameNoExt = e.Name.Substring(0, e.Name.IndexOf("."));
archivePath = parentDirectory.FullName + "\\Archive\\" + Settings._sys.User.UserID + "_" + DateTime.Today.Date.ToString("ddMMMMyyyy") + "_" + fileNameNoExt + "_" + x.ToString() + ".xlsx";
}
fileSystemWatcher1.EnableRaisingEvents = false;
try
{
while (IsFileReady(e.FullPath) != true)
{
Console.WriteLine("Waiting for file to be released by process");
continue;
}
File.Move(e.FullPath, archivePath);
File.SetLastWriteTimeUtc(archivePath, DateTime.UtcNow);
}
catch (Exception err)
{
//log error
}
fileSystemWatcher1.EnableRaisingEvents = true;
string msg = string.Format("File {0} | {1}",
e.FullPath, e.ChangeType);
}
catch(Exception err)
{
//logs error
}
}
答案 0 :(得分:2)
这部分代码看起来很重要
fileSystemWatcher1.EnableRaisingEvents = false;
try
{
while (IsFileReady(e.FullPath) != true)
{
Console.WriteLine("Waiting for file to be released by process");
continue;
}
它可以保持在禁用状态,直到文件没有准备好......
答案 1 :(得分:0)
请注意,当超出缓冲区大小时,FileSystemWatcher可能会错过事件。为避免遗漏事件,请遵循以下准则:
通过设置InternalBufferSize属性来增加缓冲区大小。
避免观看具有长文件名的文件,因为长文件名有助于填充缓冲区。
考虑使用较短的名称重命名这些文件。
尽可能缩短您的事件处理代码。
我会看第一个和最后一个子弹。
在我看来,您的事件处理代码不是很短。它包含一个while
循环,可能需要一些时间才能完成。也许事件处理程序应该只是将路径添加到ConcurrentQueue并退出。单独的工作进程将轮询队列并采取适当的操作。