c# - 释放文件锁时收到通知

标签 c# .net filesystemwatcher ntfs filelock

[使用C#和Windows作为平台]

我有一台相机,可以将 JPG 文件写入我 PC 的本地文件夹中。我想加载相机丢弃的每个文件,所以我有一个 FileSystemWatcher,它会在创建新图片时通知我,但相机在写入文件时锁定了文件,所以如果我尝试加载它在收到创建文件的通知后,我收到一个异常消息,提示文件已锁定

目前,我有一个 while 循环(带有 Thread.Sleep)每 0.2 秒重试一次加载图像,但感觉有点脏。

有没有更优雅的方法来等到锁被释放,这样我就可以加载文件并确保它不再被使用?

最佳答案

您将无法绕过试错法,即尝试打开文件,捕获 IOException,然后重试。但是,您可以像这样在单独的类中隐藏这种丑陋之处:

public class CustomWatcher
{
    private readonly FileSystemWatcher watcher;
    public event EventHandler<FileSystemEventArgs> 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;
    }
}

这个“watcher”可以这样使用:

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

免责声明:CustomWatcher 可能需要 IDisposable 并适本地处理 FileSystemWatcher。该代码仅显示了如何实现所需功能的示例。

关于c# - 释放文件锁时收到通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36205450/

相关文章:

c# - C# 中左移位的奇怪行为

c# - 使用 C# 调整透明图像的大小

.net - IIS 7 上的 net.tcp WCF 服务(mex 终结点)出现 "There is no compatible TransportManager found"错误

c# - 如何知道哪个 FileSystemWatcher 正在调用方法?

c# - StructLayout 仅适用于结构?

c# - 从方法返回更新

c# - 列表框中的图像加载问题,WP7

c# - 尝试使用 FileStream 和 StreamWriter 编写 LogFile 的异常

Python:同时两个循环

c++ - Mac OS X 的文件系统观察器