【问题标题】:FileSystemWatcher to monitor moved files [duplicate]FileSystemWatcher 监视移动的文件 [重复]
【发布时间】:2011-08-05 17:30:55
【问题描述】:

可能重复:
Detecting moved files using FileSystemWatcher

我正在尝试使用 FileSystemWatcher 监控移动的文件,并在此过程中获得了一些帮助:

Using FileSystemWatcher with multiple files

但是,我发现我必须能够同时使用 Deleted 和 Created 事件,才能获取文件移动位置的路径以及文件移动位置的路径。但是当我为 Delete 事件添加类似代码时,我只能触发一个或另一个事件。这似乎是我连接事件的顺序决定了哪个事件将运行。因此,如果我将 Created 事件放在接线代码的最后,它将运行,反之亦然,如果我将 Delete 接线放在最后,它将运行,但不是 Created。

代码如下:

public class FileListEventArgs : EventArgs
{
    public List<string> FileList { get; set; }
}

public class Monitor
{
    private List<string> filePaths;
    private List<string> deletedFilePaths;
    private ReaderWriterLockSlim rwlock;
    private Timer processTimer;
    private Timer deletionTimer;
    public event EventHandler FileListCreated;
    public event EventHandler FileListDeleted;


    public void OnFileListCreated(FileListEventArgs e)
    {
        if (FileListCreated != null)
            FileListCreated(this, e);
    }

    public void OnFileListDeleted(FileListEventArgs e)
    {
        if (FileListDeleted != null)
            FileListDeleted(this, e);
    }

    public Monitor(string path)
    {
        filePaths = new List<string>();
        deletedFilePaths = new List<string>();

        rwlock = new ReaderWriterLockSlim();

        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Filter = "*.*";
        watcher.Deleted += new FileSystemEventHandler(watcher_Deleted);
        watcher.Created += watcher_FileCreated;


        watcher.Path = path;
        watcher.IncludeSubdirectories = true;
        watcher.EnableRaisingEvents = true;
    }


    private void ProcessQueue()
    {
        try
        {
            Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
            rwlock.EnterReadLock();

        }
        finally
        {
            if (processTimer != null)
            {
                processTimer.Stop();
                processTimer.Dispose();
                processTimer = null;
                OnFileListCreated(new FileListEventArgs { FileList = filePaths });
                filePaths.Clear();
            }
            rwlock.ExitReadLock();
        }
    }

    private void ProcessDeletionQueue()
    {
        try
        {
            Console.WriteLine("Processing queue, " + deletedFilePaths.Count + " files created:");
            rwlock.EnterReadLock();

        }
        finally
        {
            if (processTimer != null)
            {
                processTimer.Stop();
                processTimer.Dispose();
                processTimer = null;
                OnFileListDeleted(new FileListEventArgs { FileList = deletedFilePaths });

                deletedFilePaths.Clear();
            }
            rwlock.ExitReadLock();
        }
    }

    void watcher_FileCreated(object sender, FileSystemEventArgs e)
    {
        try
        {
            rwlock.EnterWriteLock();
            filePaths.Add(e.FullPath);

            if (processTimer == null)
            {
                // First file, start timer.
                processTimer = new Timer(2000);
                processTimer.Elapsed += (o, ee) => ProcessQueue();
                processTimer.Start();
            }
            else
            {
                // Subsequent file, reset timer. 
                processTimer.Stop();
                processTimer.Start();
            }

        }
        finally
        {
            rwlock.ExitWriteLock();
        }
    }

    void watcher_Deleted(object sender, FileSystemEventArgs e)
    {
        try
        {
            rwlock.EnterWriteLock();
            deletedFilePaths.Add(e.FullPath);

            if (deletionTimer == null)
            {
                // First file, start timer.
                deletionTimer = new Timer(2000);
                deletionTimer.Elapsed += (o, ee) => ProcessDeletionQueue();
                deletionTimer.Start();
            }
            else
            {
                // Subsequent file, reset timer. 
                deletionTimer.Stop();
                deletionTimer.Start();
            }

        }
        finally
        {
            rwlock.ExitWriteLock();
        }
    }

那么,我该如何获取文件所在的原始路径以及它们被移动的新路径? (请参阅第一个问题,了解为什么存在计时器代码以推迟对事件的处理,直到所有文件都已在多文件移动中移动)。

【问题讨论】:

  • 我不这么认为。就像那篇文章一样,我使用文件名来比较文件没有问题。问题是我无法同时触发删除和创建事件。或者至少我所看到的是创建事件被触发并且删除还没有这样做。在我的主类中,我需要获取创建的文件列表并将其与已删除的文件列表进行比较,但已删除的文件列表为空,而创建的文件列表已填充。

标签: c# filesystemwatcher


【解决方案1】:

您声明了两个计时器,但您只使用其中一个(在进程删除队列方法中使用相同的一个)。所以看起来像是一个简单的复制/粘贴错误。

【讨论】:

  • 谢谢,这是我试图让它工作的尝试,但我错过了用你所说的复制和粘贴来改变一些东西。虽然它并没有帮助解决这个错误,但它让我重新审视了一遍,我发现如果我在同一个 ProcessQueue 方法中触发这两个事件,它确实有效,所以我会为此归功于你。
【解决方案2】:

我发现 FileSystemWatcher 事件没有排队(警告:这是大约 8 年前)。

如果您正在处理一个文件,并且在处理过程中创建了 3 个新文件,您将不会收到这 3 个事件。

处理文件后,您可能需要手动检查目录是否有其他更改。

【讨论】:

  • 好吧,我确实得到了 3 个用于移动 3 个文件的事件……但问题是我无法同时触发删除和创建事件,只能触发其中一个。
  • 你只是监控一个目录吗?如果你移动一个文件,它就不能留在同一个目录中。如果文件被移出,您将获得已删除的事件。如果文件被移入,您将获得创建的事件。我不明白你怎么能同时得到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多