我正在用c#写一个程序,需要反复访问1个图像文件。大多数时候它是有效的,但如果我的计算机运行得很快,它会在文件保存回文件系统之前尝试访问该文件,并抛出一个错误:

文件正在被另一个进程使用

我想找到一个解决这个问题的方法,但我在谷歌上的所有搜索都只能通过使用异常处理来创建检查。这违背了我的宗教信仰,所以我想知道有没有更好的方法?


当前回答

也许您可以使用FileSystemWatcher并观察“已更改”事件。

我自己还没用过这个,但也许值得一试。如果对于这种情况,文件系统监控器显得有点重,那么我将使用try/catch/sleep循环。

其他回答

更新了该解决方案的说明:使用FileAccess检查。对于只读文件,ReadWrite将失败,因此解决方案已修改为使用FileAccess.Read进行检查。

原: 在过去的几年里,我一直在使用这段代码,没有遇到过任何问题。

理解你在使用异常时的犹豫,但你不能总是避免它们:

protected virtual bool IsFileLocked(FileInfo file)
{
    try
    {
        using(FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
        {
            stream.Close();
        }
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }

    //file is not locked
    return false;
}

你可以使用我的库来访问多个应用程序中的文件。

您可以从nuget: install - package Xabe安装它。FileLock

如果你想了解更多信息,请检查 https://github.com/tomaszzmuda/Xabe.FileLock

ILock fileLock = new FileLock(file);
if(fileLock.Acquire(TimeSpan.FromSeconds(15), true))
{
    using(fileLock)
    {
        // file operations here
    }
}

fileLock。Acquire方法仅当可以锁定该对象的文件独占时才返回true。 但是上传文件的应用程序也必须在文件锁中进行上传。 如果对象不可访问,方法返回false。

也许您可以使用FileSystemWatcher并观察“已更改”事件。

我自己还没用过这个,但也许值得一试。如果对于这种情况,文件系统监控器显得有点重,那么我将使用try/catch/sleep循环。

我所知道的唯一方法是使用Win32独占锁API,这不是太快,但例子存在。

对于大多数人来说,一个简单的解决方案就是尝试/捕捉/睡眠循环。

尝试将文件移动/复制到临时目录。如果可以的话,它没有锁,您可以安全地在临时目录中工作而不需要锁。否则就在x秒内再移动一次。