【问题标题】:FileSystemWatcher triggers for filestream openFileSystemWatcher 触发文件流打开
【发布时间】:2010-02-09 05:12:33
【问题描述】:

我有一个文件系统观察器,它会在文件被修改时触发一个事件。一旦锁定被删除,我想从该文件中读取。目前,我只是在触发事件后尝试打开文件,当正在复制大文件时,文件锁定会在事件发送后保持一段时间,从而防止文件被打开以进行读取访问。

有什么建议吗?

【问题讨论】:

    标签: c# filestream filesystemwatcher


    【解决方案1】:

    这实际上有点笨拙,除非自从我上次处理它以来问题空间发生了显着变化。

    最简单的方法是简单地尝试打开文件,捕获生成的IOException,如果文件被锁定,则将其添加到队列中以供稍后检查。您不能只尝试处理传入的每个文件,因为在各种情况下都会为同一个文件生成多个事件,因此对每个接收到的事件设置重试循环可能会很快变成一场灾难。您需要将它们排队,并定期检查队列。

    这是一个可以帮助你解决这个问题的基本类模板:

    public class FileMonitor : IDisposable
    {
        private const int PollInterval = 5000;
    
        private FileSystemWatcher watcher;
        private HashSet<string> filesToProcess = new HashSet<string>();
        private Timer fileTimer;  // System.Threading.Timer
    
        public FileMonitor(string path)
        {
            if (path == null)
                throw new ArgumentNullException("path");
    
            watcher = new FileSystemWatcher();
            watcher.Path = path;
            watcher.NotifyFilter = NotifyFilters.FileName;
            watcher.Created += new FileSystemEventHandler(FileCreated);
            watcher.EnableRaisingEvents = true;
    
            fileTimer = new Timer(new TimerCallback(ProcessFilesTimer),
                null, PollInterval, Timeout.Infinite);
        }
    
        public void Dispose()
        {
            fileTimer.Dispose();
            watcher.Dispose();
        }
    
        private void FileCreated(object source, FileSystemEventArgs e)
        {
            lock (filesToProcess)
            {
                filesToProcess.Add(e.FullPath);
            }
        }
    
        private void ProcessFile(FileStream fs)
        {
            // Your code here...
        }
    
        private void ProcessFilesTimer(object state)
        {
            string[] currentFiles;
            lock (filesToProcess)
            {
                currentFiles = filesToProcess.ToArray();
            }
            foreach (string fileName in currentFiles)
            {
                TryProcessFile(fileName);
            }
            fileTimer.Change(PollInterval, Timeout.Infinite);
        }
    
        private void TryProcessFile(string fileName)
        {
            FileStream fs = null;
            try
            {
                FileInfo fi = new FileInfo(fileName);
                fs = fi.OpenRead();
            }
            catch (IOException)
            {
                // Possibly log this error
                return;
            }
    
            using (fs)
            {
                ProcessFile(fs);
            }
    
            lock (filesToProcess)
            {
                filesToProcess.Remove(fileName);
            }
        }
    }
    

    (注意 - 我在这里从记忆中回忆起这个,所以它可能并不完美 - 如果它有问题,请告诉我。)

    【讨论】:

    • 很好,这是我在等待时使用的。我使用了超时和重试等待,我希望有更优雅的东西,但是哦,好吧 ;) (感谢一百万为出色的回复付出的努力)
    猜你喜欢
    • 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
    相关资源
    最近更新 更多