我有一些代码,当它执行时,它抛出一个IOException,说
进程无法访问文件'filename',因为它正在被 另一个进程
这意味着什么?我能做些什么?
我有一些代码,当它执行时,它抛出一个IOException,说
进程无法访问文件'filename',因为它正在被 另一个进程
这意味着什么?我能做些什么?
当前回答
问题
一个是绑定打开文件System.IO.File。使用此方法打开(path, FileMode),并希望对文件进行共享访问
如果你读了System.IO.File的文档。Open(path, FileMode),它显式地表示它不允许共享
解决方案
你必须使用其他覆盖文件共享
using FileStream fs = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
文件共享。读
其他回答
我得到这个错误是因为我在执行File。移动到没有文件名的文件路径时,需要在目标中指定完整路径。
使用FileShare修复了我打开文件的问题,即使它被另一个进程打开。
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
}
正如本文中的其他回答所指出的,要解决这个错误,您需要仔细检查代码,以了解文件被锁定的位置。
在我的例子中,我在执行移动操作之前将文件作为电子邮件附件发送出去。
所以文件被锁定了几秒钟,直到SMTP客户端完成发送电子邮件。
我采取的解决方案是先移动文件,然后再发送电子邮件。这为我解决了问题。
另一个可能的解决方案,正如Hudson之前指出的,应该是在使用后处理对象。
public static SendEmail()
{
MailMessage mMailMessage = new MailMessage();
//setup other email stuff
if (File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mMailMessage.Attachments.Add(attachment);
attachment.Dispose(); //disposing the Attachment object
}
}
我遇到了这个问题,通过下面的代码解决了这个问题
var _path=MyFile.FileName;
using (var stream = new FileStream
(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// Your Code! ;
}
原因是什么?
错误消息非常清楚:您试图访问一个文件,但它无法访问,因为另一个进程(甚至是相同的进程)正在对它做一些事情(并且它不允许任何共享)。
调试
它可能很容易解决(也可能很难理解),这取决于您的具体场景。让我们看看。
您的进程是唯一访问该文件的进程 你确定另一个过程是你自己的过程。如果您知道您在程序的另一部分打开了该文件,那么首先您必须检查在每次使用后是否正确地关闭了文件句柄。下面是这个错误的代码示例:
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
此模式还将确保在异常情况下文件不会保持打开状态(这可能是文件正在使用的原因:出错了,没有人关闭它;请看这篇文章的例子)。
If everything seems fine (you're sure you always close every file you open, even in case of exceptions) and you have multiple working threads, then you have two options: rework your code to serialize file access (not always doable and not always wanted) or apply a retry pattern. It's a pretty common pattern for I/O operations: you try to do something and in case of error you wait and try again (did you ask yourself why, for example, Windows Shell takes some time to inform you that a file is in use and cannot be deleted?). In C# it's pretty easy to implement (see also better examples about disk I/O, networking and database access).
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. 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枚举命令操作系统允许其他进程(或你自己进程的其他部分)并发访问同一个文件。
using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}
In this example I showed how to open a file for writing and share for reading; please note that when reading and writing overlaps, it results in undefined or invalid data. It's a situation that must be handled when reading. Also note that this doesn't make access to the stream thread-safe, so this object can't be shared with multiple threads unless access is synchronized somehow (see previous links). Other sharing options are available, and they open up more complex scenarios. Please refer to MSDN for more details.
一般来说,N个进程可以一起从同一个文件中读取,但只有一个进程应该写入,在受控的情况下,你甚至可以启用并发写入,但这不能在这个答案中的几个文本段落中普遍化。
是否可以解锁另一个进程使用的文件?这并不总是安全的,也不那么容易,但是的,这是可能的。