微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

IOException:该进程无法访问文件“文件路径”,因为它正在被另一个进程使用

如何解决IOException:该进程无法访问文件“文件路径”,因为它正在被另一个进程使用

原因是什么?

错误消息非常清楚:您正在尝试访问文件,并且无法访问该文件,因为另一个进程(甚至同一个进程)正在对该文件执行某些操作(并且不允许任何共享)。

调试

根据您的特定情况,这可能很容易解决(或很难理解)。让我们来看一些。

的进程。 您确定 一个 进程是您自己的进程。如果您知道在程序的另一部分中打开了该文件,则首先必须检查每次使用后是否正确关闭文件句柄。这是带有此错误代码示例:

var stream = new FileStream(path, FileAccess.Read);
var reader = new StreamReader(stream);
// Read data from this file, when I'm done I don't need it any more
File.Delete(path); // IOException: file is in use

幸运地FileStream实现Idisposable,因此很容易将所有代码包装在一条using语句中:

using (var stream = File.Open("myfile.txt", FileMode.Open)) {
    // Use stream
}

// Here stream is not accessible and it has been closed (also if
// an exception is thrown and stack unrolled

这种模式还可以确保在出现异常的情况下不会打开文件(这可能是文件正在使用的原因:出了点问题,没有人关闭它;请参阅示例)。

如果一切看起来都很好(即使有例外情况,您也要确保总是关闭打开的每个文件),并且有多个工作线程,那么您有两种选择:重新编写代码以序列化文件访问权限(不总是可行,也不一定想要)或应用重试模式 。这是I / O操作的一种非常常见的模式:您尝试做一些事情,并且在出现错误的情况下等待并再次尝试(您是否问自己为什么,例如Windows Shell需要一些时间来通知文件正在使用中并不能删除?)。在C#中,它很容易实现(另请参见有关磁盘I / O网络数据库访问的更好的示例)。

private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;

for (int i=1; i <= NumberOfRetries; ++i) {
    try {
        // Do stuff with file
        break; // When done we can break loop
    }
    catch (IOException e) when (i <= NumberOfRetries) {
        // You may check error code to filter some exceptions, not every error
        // can be recovered.
        Thread.Sleep(DelayOnRetry);
    }
}

请注意我们在StackOverflow上经常看到的常见错误

var stream = File.Open(path, FileOpen.Read);
var content = File.ReadAllText(path);

在这种情况下,ReadAllText()将因为文件正在使用而失败(File.open()在前一行中)。事先打开文件不仅是不必要的,而且是错误的。这同样适用于所有File不回报功能句柄 到你正在使用的文件File.ReadAllText()File.WriteallText()File.ReadAllLines()File.WriteallLines()和其他人(如File.AppendAllXyz()函数)将所有打开和关闭自己的文件

的进程如果您的进程不是唯一 的进程,则交互可能会更加困难。一个 重试模式 将帮助(如果该文件不应该是开放的其他任何人,但它是,那么你需要像Process Explorer的一个实用程序,检查 在做 什么 )。

避免的方法

如果适用,请始终使用 using 语句打开文件。如前一段所述,它将积极帮助您避免许多常见错误(有关 *

如果可能,请尝试确定谁拥有对特定文件的访问权,并通过一些众所周知的方法集中访问。例如,如果您有一个程序在其中读写的数据文件,则应将所有I / O代码装在一个类中。这将使调试更加容易(因为您始终可以在此处放置一个断点,并查看谁在做什么),并且它将成为多路访问的同步点(如果需要)。

不要忘记I / O操作总是会失败,一个常见的例子是:

if (File.Exists(path))
    File.Delete(path);

如果 有人 在之后File.Exists(),之前删除文件File.Delete(),则会IOException在您可能会误以为安全的地方丢一个文件

只要有可能,请应用 重试模式 ,如果您正在使用FileSystemWatcher,请考虑推迟操作(因为会收到通知,但应用程序可能仍专门处理该文件)。

并非总是那么容易,因此您可能需要与其他人共享访问权限。例如,如果您从头开始阅读,然后从头开始写作,则至少有两个选择。

1)FileStream与适当的同步功能共享相同的内容(因为 )。请参阅帖子以获取示例。

2)使用FileShare枚举来指示OS允许其他进程(或您自己进程的其他部分)同时访问同一文件

using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}

在这个例子中,我展示了如何打开一个文件进行写入和共享以进行读取。请注意,当读写重叠时,会导致数据未定义或无效。阅读时必须处理这种情况。还要注意,这不能访问stream线程安全的对象,因此,除非以某种方式同步访问,否则不能与多个线程共享该对象(请参阅前面的链接)。其他共享选项可用,它们打开了更复杂的方案。有关更多详细信息,请参考MSDN

通常, N个 进程可以一起读取同一文件,但是只能写入一个文件,在受控的情况下,您甚至可以启用并发写入,但这不能在此答案中的几个文本段落中进行概括。

是否可以 另一个进程使用的文件?它并不总是很安全,也不是那么容易,但是是的,有可能

解决方法

我有一些代码,当它执行时会抛出一个IOException,说

该进程无法访问文件“文件名”,因为它正在被另一个进程使用

这是什么意思,我该怎么办?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。