释放文件锁时得到通知 [英] Getting notified when a file lock is released

查看:110
本文介绍了释放文件锁时得到通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

[Using C# and Windows as platform]

我有一台照相机,可以将JPG文件写入PC的本地文件夹中。我想加载相机掉落的每个文件,所以我有一个FileSystemWatcher,它会在创建新图片时通知我,但是相机在写入文件时会锁定文件,因此,如果我尝试加载它刚收到通知后,我得到一个例外,说文件已被锁定

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 FileSystemWatcher that notifies me whenever a new picture is created, but the camera locks the file while it's being written, so if I try to load it just after being notified of its creation, I get an exception saying that the file is locked.

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

Currently, I have a while loop (with a Thread.Sleep) that retries to load the image every 0.2 seconds, but it feels a bit dirty.

有没有更优雅的方法来等待锁被锁住释放,因此我可以加载该文件以确保不再使用它??

Is there a more elegant way to wait until the lock has been released, so I can load the file being sure that it's no longer used??

推荐答案

您将无法解决该问题反复试验的方法,即尝试打开文件,捕获IOException,然后重试。但是,您可以将此类丑陋隐藏在单独的类中,如下所示:

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

此观察者可以这样使用:

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

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

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.

这篇关于释放文件锁时得到通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆