C# 文件正被另一个进程使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16285342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# file is being used by another process
提问by Doctorslo
I am not sure how can I solve my problem. From time to time I get the error: "The process cannot access the file 'xxxx' because it is being used by another proces".
我不确定如何解决我的问题。我不时收到错误消息:“进程无法访问文件‘xxxx’,因为它正被另一个进程使用”。
Here is my method where the error happens:
这是我发生错误的方法:
private static void write_history(int index, int time_in_sec, int[] sent_resources)
{
string filepath = "Config\xxx.txt";
int writing_index = 0;
if (File.Exists(filepath))
{
System.Threading.Thread.Sleep(5000);
StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read));
string temp = reader.ReadToEnd();
reader.Close();
for (int i = 0; i < 20; i++)
{
if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
{
writing_index = i;
break;
}
}
}
System.Threading.Thread.Sleep(5000);
// write to the file
StreamWriter writer = new StreamWriter(filepath, true);
writer.WriteLine("<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
writer.Close();
}
And the error I get:
我得到的错误:
************** Exception Text **************
System.IO.IOException: The process cannot access the file 'Config\xxx.txt' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
回答by Sam I am says Reinstate Monica
my guess is that your FileStream(the one you're passing into your StreamReaderconstructor) is not getting closed
我的猜测是你的FileStream(你传递给StreamReader构造函数的那个)没有被关闭
StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read));
Put that statement in a using statement, to make sure all your ends are tied
将该语句放在 using 语句中,以确保您的所有目的都被绑定
using(StreamReader reader = new StreamReader(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
//the using statement will handle the closing for you
}
回答by Martin Mulder
- Use
usingaround all your objects that areIDisposable.usingwill ALWAYS call the methodDispose, even if there is an exception. - You did close your reader, but did not close the filestream.
This code can be made much shorter, see my second example at the bottom of my answer.
private static void write_history(int index, int time_in_sec, int[] sent_resources) { string filepath = "Config\xxx.txt"; int writing_index = 0; if (File.Exists(filepath)) { System.Threading.Thread.Sleep(5000); using(FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read) using(StreamReader reader = new StreamReader(stream)) { string temp = reader.ReadToEnd(); } for (int i = 0; i < 20; i++) { if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1) { writing_index = i; break; } } } System.Threading.Thread.Sleep(5000); // write to the file using(StreamWriter writer = new StreamWriter(filepath, true)) { writer.WriteLine("<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">"); } }
using在您所有的对象周围使用IDisposable.using将始终调用方法Dispose,即使有异常。- 您确实关闭了阅读器,但没有关闭文件流。
这段代码可以更短,请参阅我的答案底部的第二个示例。
private static void write_history(int index, int time_in_sec, int[] sent_resources) { string filepath = "Config\xxx.txt"; int writing_index = 0; if (File.Exists(filepath)) { System.Threading.Thread.Sleep(5000); using(FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read) using(StreamReader reader = new StreamReader(stream)) { string temp = reader.ReadToEnd(); } for (int i = 0; i < 20; i++) { if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1) { writing_index = i; break; } } } System.Threading.Thread.Sleep(5000); // write to the file using(StreamWriter writer = new StreamWriter(filepath, true)) { writer.WriteLine("<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">"); } }
Shorter version:
较短的版本:
private static void write_history(int index, int time_in_sec, int[] sent_resources)
{
string filepath = "Config\xxx.txt";
int writing_index = 0;
if (File.Exists(filepath))
{
System.Threading.Thread.Sleep(5000);
string temp = File.ReadAllText(filepath);
for (int i = 0; i < 20; i++)
{
if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
{
writing_index = i;
break;
}
}
}
System.Threading.Thread.Sleep(5000);
// write to the file
File.WriteAllText(filepath, "<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
}
In case of multi threading:
如果是多线程:
private static readonly object _syncLock = new object();
private static void write_history(int index, int time_in_sec, int[] sent_resources)
{
lock(_syncLock)
{
string filepath = "Config\xxx.txt";
int writing_index = 0;
if (File.Exists(filepath))
{
System.Threading.Thread.Sleep(5000);
string temp = File.ReadAllText(filepath);
for (int i = 0; i < 20; i++)
{
if (temp.IndexOf("<hst_" + i.ToString() + ">") == -1)
{
writing_index = i;
break;
}
}
}
System.Threading.Thread.Sleep(5000);
// write to the file
File.WriteAllText(filepath, "<hst_" + writing_index.ToString() + ">" + DateTime.Now.AddSeconds(time_in_sec).ToString() + "|" + sent_resources[0] + "|" + sent_resources[1] + "|" + sent_resources[2] + "|" + sent_resources[3] + "</hst_" + writing_index.ToString() + ">");
}
}
回答by Tombala
Your method is not thread-safe. If you're accessing this method in a multi-threaded fashion, your threads could be attempting the file access at the same time. In addition to alexn's answer of properly disposing of your StreamReader, also consider using a static object outside of your method in your class and then simply locking on that before you access the file.
您的方法不是线程安全的。如果您以多线程方式访问此方法,则您的线程可能同时尝试访问文件。除了 alexn 正确处理 StreamReader 的答案之外,还可以考虑在类中的方法之外使用静态对象,然后在访问文件之前简单地锁定它。
private static object lockObject = new object();
private static void write_history(int index
{
lock(lockObject)
{
// Access file here
}
}
回答by Eric Lippert
If you have made sure that you are genuinely opening and closing the file correctly, the most likely culprit is your virus detector. Virus detectors are notorious for observing that a log file has changed, opening it up to search it for a virus, and then while it is being read by the virus checker, an attempt to write to the file fails.
如果您确定正确打开和关闭文件,最有可能的罪魁祸首是您的病毒检测器。病毒检测器因观察日志文件已更改而臭名昭著,打开它以搜索病毒,然后在病毒检查程序读取它时,尝试写入文件失败。
If that's the case, then I would ask the vendor of your virus checker what their recommended workaround is.
如果是这种情况,那么我会询问您的病毒检查程序的供应商他们推荐的解决方法是什么。
回答by Unais.N.I
Either you can use "using" or you can force the Garbage collector to release all the references. This has resolved my issue. Review your code before applying process level or thread level changes.
您可以使用“使用”,也可以强制垃圾收集器释放所有引用。这已经解决了我的问题。在应用进程级别或线程级别更改之前查看您的代码。
example:
例子:
using(StreamWriter writer....)
{
Your Code....
}
this.deleteFiles(filepath);
Or:
或者:
GC.Collect();
this.deleteFiles(filepath);

