2008-11-10 57 views
3

我正在使用.net filewatcher监视某个文件(*。mbxml)的文件夹。我正在使用为它创建的filewatcher事件。一旦创建的事件触发,我必须将此文件移动到另一个文件夹。这种方法的问题在于,一旦文件复制开始,创建的事件就会被触发。因此,如果文件复制到正在观看的文件夹时间过长,则移动文件的代码将失败。我搜索了,我在网上找到的唯一解决方案是,您将文件移动到try-catch块中,并继续尝试复制整个文件。我不喜欢这个解决方案,如果创建的事件在整个文件复制完成或者有单独的事件发生时被解雇,情况会更好。是否有另一种方法来实现这一点?Filewatcher创建事件

回答

2

我还没有看到这样做,除了try catch块。通常在oncreate事件我设置一个布尔,试图打开文件。这决定了代码的其余部分是否继续,如果有另一种方式我也会感兴趣。

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; 
     } 
    } 
2

你能改变正在创建文件的程序吗?如果是这样,请将其更改为在一个文件夹中创建它们,然后将它们(以原子方式)移动到不同的文件夹 - 或使用不同的扩展名(真正可以跟踪的任何内容)。

1

您是否尝试过使用BinaryReader和BinaryWriter移动文件?您可以在复制文件时读取该文件,并将其写入较慢的速度,以便您的移动速度不会超过其他进程创建文件的速度。您也可以在读取之间插入一些等待时间。一旦你做了最后一次阅读并确认文件创建完成,你可以删除它。

祝你好运!

1

使用try/catch解决方案的全部原因是因为知道其他程序是否完成写入文件的唯一方法是用于文件open()调用SUCCEED。这是一个FAILURE是文件仍在写入的定义。

通常在你的情况下,一个while()循环与一个thread.sleep定时器一起使用,它不断地尝试,直到A)超时或B)成功。

0

如果我没有记错,FileWatcher会在给定的文件/文件夹中为每个IO引发几个事件。您可能能够缩小与完成关联的FileSystemEventArgs。可能有必要延迟检查文件是否可访问,但我认为这不是一个理想的解决方案。

2

来源: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

“共同文件系统,当文件从一个目录移动到另一个,几个调用onChanged和一些OnCreated和OnDeleted事件可能引发的操作可能会引发多个事件。例如,。移动文件是一个复杂的操作,由多个简单操作组成,因此引发多个事件。同样,某些应用程序(例如防病毒软件)可能会导致FileSystemWatcher检测到的其他文件系统事件。“

时间敏感您是否需要移动文件?

如果您不喜欢尝试移动它,捕捉异常并重复直到获得成功的想法,则可采取稍微不同的方法。

一旦你收到一个创建的事件,你开始监视文件的最后写入时间。一旦自上次写入时间过去了一段时间,比如两秒钟,您就可以尝试移动文件。你可能会发现“失败”的举动少了很多,但最终的结果是一样的。

2

观察上创建的事件,但等待上次写入时间更改事件。当文件完成复制时,最后的写入时间会更新。由于您正在移动文件,因此您可能只需处理最后一次写入时间更改事件。

3

你可以使你的代码由FileSystemWatcher的只是继承和fireing自己FileReady事件,像这样简单:

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); 
    } 
} 
+0

你的代码是基本相同的方法,你刚刚编写的代码在你的继承类。 – Raminder 2008-11-11 08:12:34