gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 19:31:45 27 4
gpt4 key购买 nike

我有一些代码,当它执行时,它抛出一个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

此模式还将确保文件在出现异常时不会保持打开状态(这可能是文件正在使用的原因:出现问题,没有人关闭它;请参见 this post以获取示例)。
如果一切都很好(你确信你总是关闭你打开的每一个文件,即使在异常情况下),并且你有多个工作线程,那么你有两个选项:修改你的代码来序列化文件访问(不总是可行的和不总是想要的)或者应用重试模式。对于I/O操作来说,这是一个非常常见的模式:您尝试做一些事情,如果出现错误,您就等着再试一次(您问自己为什么,例如,Windows Shell需要一些时间来通知您文件正在使用,不能删除吗?)在C语言中很容易实现(参见关于AA>, disk I/Onetworking的更好的例子)。
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()函数)都将自己打开和关闭文件。
您的进程不是唯一可以访问该文件的进程。
如果您的进程不是唯一可以访问该文件的进程,那么交互可能会更加困难。重试模式将有帮助(如果文件不应该被其他人打开,但它是,那么你需要一个实用工具,比如进程资源管理器来检查谁在做什么)。
避免的方法
如果适用,请始终使用using语句打开文件。如前一段所述,它将积极帮助您避免许多常见的错误(有关如何不使用它的示例,请参见 database access)。
如果可能的话,尝试决定谁拥有特定文件的访问权,并通过一些众所周知的方法集中访问。例如,如果您有一个数据文件供程序读写,那么您应该将所有I/O代码框在一个类中。它将使调试变得更容易(因为您始终可以在那里放置一个断点并查看谁在做什么),而且它将是多个访问的同步点(如果需要)。
别忘了I/O操作总是会失败,一个常见的例子是:
if (File.Exists(path))
File.Delete(path);

如果有人在 File.Exists()之后但在 File.Delete()之前删除了文件,那么它将在您可能错误地感到安全的地方抛出一个 IOException
只要有可能,就应用重试模式,如果您使用的是 FileSystemWatcher,请考虑推迟操作(因为您将收到通知,但应用程序可能仍以独占方式处理该文件)。
高级方案
这并不总是那么容易,所以您可能需要与其他人共享访问权限。例如,如果你从头读到尾,你至少有两个选择。
1)用适当的同步函数共享相同的 FileStream(因为它不是线程安全的)。有关示例,请参见 this postthis帖子。
2)使用 FileShare枚举来指示OS允许其他进程(或您自己进程的其他部分)同时访问同一文件。
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}

在这个例子中,我展示了如何打开一个文件进行写入和共享进行读取;请注意,当读取和写入重叠时,它会导致未定义或无效的数据。这是一种阅读时必须处理的情况。还要注意,这并不能保证对 stream线程的访问是安全的,因此除非以某种方式同步访问(参见前面的链接),否则不能将此对象与多个线程共享。其他共享选项也可用,它们打开了更复杂的场景。详情请参阅 this
一般来说,N个进程可以从同一个文件中一起读取,但只有一个应该写入,在受控的情况下,您甚至可以启用并发写入,但是这不能在本答案中的几个文本段落中被概括。
是否可以解锁另一个进程使用的文件?它并不总是安全和不那么容易,但是的, MSDN

关于c# - IOException:该进程无法访问文件“文件路径”,因为它正在被另一个进程使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55695785/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com