【问题标题】:Filewatcher created eventFilewatcher 创建事件
【发布时间】:2010-07-08 17:14:00
【问题描述】:

我正在使用 .net 文件监视程序监视某个文件夹以查找某些类型的文件 (*.mbxml)。我正在为它使用创建的 filewatcher 事件。一旦创建的事件触发,我必须将此文件移动到另一个文件夹。这种方法的问题在于,文件复制一开始就会触发 created 事件。因此,如果将文件复制到正在监视的文件夹的时间过长,则移动文件的代码将失败。我已经搜索过,我在网上找到的唯一解决方案是将文件移动到 try-catch 块中并继续尝试直到整个文件被复制。我不喜欢这个解决方案,如果创建的事件在整个文件完成复制或有一个单独的事件后被触发会更好。还有其他方法可以实现吗?

【问题讨论】:

    标签: .net


    【解决方案1】:

    您可以通过从 FileSystemWatcher 继承并触发您自己的 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);
        }
    }
    

    【讨论】:

    • 你的代码基本上是一样的方法,你只是在你的继承类中写了代码。
    【解决方案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;
            }
        }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        “常见的文件系统操作可能会引发多个事件。例如,当文件从一个目录移动到另一个目录时,可能会引发多个 OnChanged 以及一些 OnCreated 和 OnDeleted 事件。移动文件是一项复杂的操作,包括多个简单操作,因此引发多个事件。同样,某些应用程序(例如,防病毒软件)可能会导致 FileSystemWatcher 检测到的其他文件系统事件。"

        您对移动文件的要求对时间有多敏感?

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

        一旦收到 Created 事件,您就开始监控文件的最后写入时间。一旦自上次写入时间过去了一定时间,比如两秒钟,您可以尝试移动文件。您可能会发现“失败”的动作要少得多,但最终结果将是相同的。

        【讨论】:

          【解决方案5】:

          注意 on created 事件,但等待最后一次写入时间更改事件。文件复制完成后,最后一次写入时间将更新。由于您正在移动文件,因此您可能只需处理最后一次写入时间更改事件。

          【讨论】:

            【解决方案6】:

            您是否尝试过使用 BinaryReader 和 BinaryWriter 移动文件?您可能可以在复制文件时读取文件并以较慢的速度写入,这样您的移动不会超过其他进程创建文件的速度。您还可以在读取之间插入一些等待时间。完成最后一次读取并验证文件创建完成后,您可以将其删除。

            祝你好运!

            【讨论】:

              【解决方案7】:

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

              在您的情况下,通常会使用带有 thread.sleep 计时器的 while() 循环,它会一直尝试直到 A) 超时或 B) 成功。

              【讨论】:

                【解决方案8】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多