FileSystemWatcher triggers for filestream open

前端 未结 1 1559
长发绾君心
长发绾君心 2020-12-19 01:50

I have a filesystemwatcher that will trigger an event when a file is modified. I want to read from that file once the lock has been removed. At the moment I am just trying t

相关标签:
1条回答
  • 2020-12-19 02:36

    This one's actually a bit of a doozie, unless the problem space has changed significantly since I last had to deal with it.

    The easiest way is to simply try to open the file, catch the resulting IOException, and if the file is locked, add it to a queue to be checked later. You can't just try to process every file that comes in because there are all kinds of cases where multiple events will be generated for the same file, so setting up a retry loop on every single received event can turn into a disaster, fast. You need to queue them up instead and check the queue at a regular interval.

    Here is a basic class template that should help you out with this problem:

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

    (Note - I'm recalling this from memory here so it might not be perfect - let me know if it's buggy.)

    0 讨论(0)
提交回复
热议问题