我正在使用.net filewatcher监视某个文件夹(* .mbxml)。我正在使用filewatcher的创建事件。一旦创建的事件触发,我必须将此文件移动到另一个文件夹。这种方法的问题是,一旦文件复制开始,就会触发创建的事件。因此,如果文件花费太长时间来复制到正在观看的文件夹,则移动文件的代码将失败。我搜索过,我在网上找到的唯一解决方案就是你在try-catch块中移动文件并继续尝试直到整个文件被复制。我不喜欢这个解决方案,如果在整个文件完成复制后创建的事件被触发,或者有一个单独的事件,它会更好。还有另一种方法可以达到这个目的吗?
答案 0 :(得分:3)
只需继承FileSystemWatcher并触发自己的FileReader事件,就可以简化代码,如下所示:
public class CustomFileSystemWatcher : System.IO.FileSystemWatcher
{
public CustomFileSystemWatcher()
{
this.Created += new FileSystemEventHandler(CustomFileSystemWatcher_Created);
}
private void CustomFileSystemWatcher_Created(object sender, FileSystemEventArgs e)
{
ThreadPool.QueueUserWorkItem((n) => { WaitFileReady(e); });
}
private void WaitFileReady(FileSystemEventArgs e)
{
while (true)
{
try
{
using (FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
//exit
break;
}
}
catch (Exception)
{
//wait if you like
Thread.Sleep(100);
}
}
OnFileReady(e);
}
public event FileSystemEventHandler FileReady;
protected virtual void OnFileReady(FileSystemEventArgs e)
{
if (this.EnableRaisingEvents && FileReady != null) FileReady(this, e);
}
}
答案 1 :(得分:2)
您是否可以更改创建文件的程序?如果是这样,更改它以在一个文件夹中创建它们然后将它们(原子地)移动到另一个文件夹 - 或者使用不同的扩展名(您可以跟踪的任何内容)。
答案 2 :(得分:2)
除了使用try catch块之外,我还没有看到这样做。通常在oncreate事件上我设置了一个试图打开文件的bool。这确定了代码的其余部分是否继续,如果还有其他方式我也会感兴趣。
private static bool creationComplete(string fileName)
{
// if the file can be opened it is no longer locked and now available
try
{
using (FileStream inputStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
return true;
}
}
catch (IOException)
{
return false;
}
}
答案 3 :(得分:2)
自: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
“公共文件系统操作可能会引发多个事件。例如,当文件从一个目录移动到另一个目录时,可能会引发多个OnChanged和一些OnCreated和OnDeleted事件。移动文件是一个复杂的操作,包括多个简单操作,因此引发多个事件。同样,某些应用程序(例如,防病毒软件)可能会导致FileSystemWatcher检测到其他文件系统事件。“
移动文件的要求对时间敏感度如何?
如果您不喜欢尝试移动它,捕获异常并重复直到获得成功,那么您可以采取稍微不同的方法。
一旦收到Created事件,您就开始监视文件的上次写入时间。从上次写入时间开始经过一段时间后,比如两秒钟,您可以尝试移动文件。你可能会发现那里“失败”的动作要少得多,但最终结果会是一样的。
答案 4 :(得分:2)
注意on on created事件,但等待上次写入时间更改事件。复制完文件后,将更新上次写入时间。由于您正在移动文件,因此您可以只处理上次写入时间更改事件。
答案 5 :(得分:1)
您是否尝试过使用BinaryReader和BinaryWriter移动文件?您可以在复制时读取文件并将其写入较慢的速度,这样您的移动速度就不会超过其他进程创建文件的速度。您还可以在读取之间插入一些等待时间。完成上次读取并验证文件创建完成后,您可以将其删除。
祝你好运!答案 6 :(得分:1)
使用try / catch解决方案的全部原因是因为知道其他程序是否已完成写入文件的唯一方法是对SUCCEED的文件open()调用。那是FAILURE是仍在写入的文件的定义。
通常在你的情况下,while()循环与thread.sleep定时器一起使用,它会一直尝试,直到A)超时或B)成功。
答案 7 :(得分:0)
如果我没记错的话,FileWatcher会在给定的文件/文件夹上为每个IO引发几个事件。您可以缩小与完成关联的FileSystemEventArgs。可能有必要推迟检查文件是否可访问,但我认为这是一个不太理想的解决方案。