Getting notified when a file lock is released

后端 未结 1 1292
眼角桃花
眼角桃花 2021-01-19 04:39

[Using C# and Windows as platform]

I have a camera that writes JPG files to a local folder in my PC. I want to load each file the camera drops, so I have a FileSyste

1条回答
  •  盖世英雄少女心
    2021-01-19 05:38

    You will not be able to get around trial and error approach, i.e., try to open the file, catch IOException, try again. However, you can hide this ugliness in a separate class like so:

    public class CustomWatcher
    {
        private readonly FileSystemWatcher watcher;
        public event EventHandler CreatedAndReleased;
    
        public CustomWatcher(string path)
        {
            watcher = new FileSystemWatcher(path, "*.jpg");
            watcher.Created += OnFileCreated;
            watcher.EnableRaisingEvents = true;
        }
    
        private void OnFileCreated(object sender, FileSystemEventArgs e)
        {
            // Running the loop on another thread. That means the event
            // callback will be on the new thread. This can be omitted
            // if it does not matter if you are blocking the current thread.
            Task.Run(() =>
            {
                // Obviously some sort of timeout could be useful here.
                // Test until you can open the file, then trigger the CreeatedAndReleased event.
                while (!CanOpen(e.FullPath))
                {
                    Thread.Sleep(200);
                }
                OnCreatedAndReleased(e);
            });
        }
    
        private void OnCreatedAndReleased(FileSystemEventArgs e)
        {
            CreatedAndReleased?.Invoke(this, e);
        }
    
        private static bool CanOpen(string file)
        {
            FileStream stream = null;
            try
            {
                stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None);
            }
            catch (IOException)
            {
                return false;
            }
            finally
            {
                stream?.Close();
            }
            return true;
        }
    }
    

    This "watcher" can be used like this:

    var watcher = new CustomWatcher("path");
    watcher.CreatedAndReleased += (o,e) => 
    {
        // Now, your watcher has managed to open and close the file,
        // so the camera is done with it. Obviously, any other application
        // is able to lock it before this code manages to open the file.
        var stream = File.OpenRead(e.FullPath);
    }
    

    Disclaimer: CustomWatcher probably needs to be IDisposable and dispose of the FileSystemWatcher appropriately. The code merely shows an example of how to achieve the desired functionality.

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