C#进程无法访问文件”’,因为它正由另一个进程使用

代码片段只是将字符串写入名为“all_results.txt”的文本文件中。 我在File.WriteAllText中实现了错误。 在网上搜索解决方案之后,我尝试使用FileStream和StreamWriter作为替代品。 问题仍然存在。

它给了我:

IOException未处理:进程无法访问文件’C:\ Users \ MadDebater \ Desktop \ ConsoleTest1 \ ConsoleTest \ bin \ Debug \ all_results.txt’,因为它正由另一个进程使用。

奇怪的是,错误是随意发生的。 它可能是在第3次循环或第45次循环之前遇到错误。 我提供了该类的完整代码,以防问题比看上去更深。 我确定它与我的病毒扫描程序或其他任何东西无关。

try { using (FileStream stream = new FileStream(@"all_results.txt", FileMode.Create)) // Exception here { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine(result); writer.Dispose(); writer.Close(); } stream.Dispose(); stream.Close(); } } catch (IOException ex) { Console.WriteLine(ex); } 

即使我尝试这个,它仍然失败。

 try { File.WriteAllText(@"all_results.txt", result); // Exception here } catch (IOException ex) { Console.WriteLine(ex.Message); } 

以下是该课程的完整代码。 它旨在接收Twitter推文列表,并逐个使用贝叶斯分类对它们进行分类。

  using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using BayesClassifier; using System.Text.RegularExpressions; namespace ConsoleTest { class Analyzer { public static void Analyzing(List all_results) { Reducting(all_results); Classifying(); } public static void Reducting(List all_results) { //Reductor //Precondition: List results all_results.ForEach(delegate(String text) { const string ScreenNamePattern = @"@([A-Za-z0-9\-_&;]+)"; const string HashTagPattern = @"#([A-Za-z0-9\-_&;]+)"; const string HyperLinkPattern = @"(http://\S+)\s?"; string result = text; if (result.Contains("http://")) { var links = new List(); foreach (Match match in Regex.Matches(result, HyperLinkPattern)) { var url = match.Groups[1].Value; if (!links.Contains(url)) { links.Add(url); result = result.Replace(url, String.Format("")); } } } if (result.Contains("@")) { var names = new List(); foreach (Match match in Regex.Matches(result, ScreenNamePattern)) { var screenName = match.Groups[1].Value; if (!names.Contains(screenName)) { names.Add(screenName); result = result.Replace("@" + screenName, String.Format("")); } } } if (result.Contains("#")) { var names = new List(); foreach (Match match in Regex.Matches(result, HashTagPattern)) { var hashTag = match.Groups[1].Value; if (!names.Contains(hashTag)) { names.Add(hashTag); result = result.Replace("#" + hashTag, String.Format("")); } } } // Write into text file /* try { using (FileStream stream = new FileStream(@"all_results.txt", FileMode.Create)) // Exception here { using (StreamWriter writer = new StreamWriter(stream)) { writer.WriteLine(result); writer.Dispose(); writer.Close(); } stream.Dispose(); stream.Close(); } } catch (IOException ex) { Console.WriteLine(ex); } */ try { File.WriteAllText(@"all_results.txt", result); // Exception here } catch (IOException ex) { Console.WriteLine(ex.Message); } }); } public static void Classifying() { // Classifying BayesClassifier.Classifier m_Classifier = new BayesClassifier.Classifier(); m_Classifier.TeachCategory("Positive", new System.IO.StreamReader("POSfile.txt")); m_Classifier.TeachCategory("Negative", new System.IO.StreamReader("NEGfile.txt")); Dictionary newscore; newscore = m_Classifier.Classify(new System.IO.StreamReader("all_results.txt")); PrintResults(newscore); } public static void PrintResults(Dictionary newscore) { foreach (KeyValuePair p in newscore) { Console.WriteLine(p.Key + ", " + p.Value); } List list = new List(); using (StreamReader reader = new StreamReader("all_results.txt")) { string line; while ((line = reader.ReadLine()) != null) { list.Add(line); // Add to list. Console.WriteLine(line); // Write to console. } reader.Close(); } //PrintSentiment(newscore); } public static void PrintSentiment(Dictionary newscore) { // if difference < 2, neutral // if neg < pos, pos // if pos < neg, neg double pos = newscore["Positive"]; double neg = newscore["Negative"]; string sentiment = ""; if (Math.Abs(pos - neg) < 1.03) { sentiment = "NEUTRAL"; } else { if (neg < pos) { sentiment = "POSITIVE"; } else if (pos < neg) { sentiment = "NEGATIVE"; } } Console.WriteLine(sentiment); // append tweet_collection to final_results  list // append sentiment tag to the final_results  list // recursive } } } 

不要在FileStream和StreamWriter上调用Dispose()和Close(),这将由using子句自动处理。

使用像filemon这样的实用程序来检查哪些进程正在使用该文件。

更新:从我读到的过程监视器与filemon非常相似。 从这些工具中的任何一个,您都可以找到哪个进程在何时访问了您的文件。 您可以在开始监视之前为文件添加filter。

您可以尝试的另一件事是在文件存在时获取锁定。

也许文件是由病毒扫描程序或Windows索引服务访问的?

尝试将文件写入调试文件夹之外的另一个目录。

只是一个“疯狂的镜头” – 如果你把文件放在一个更可预测的位置,比如’c:\ all_results.txt’,它会有帮助吗?

尝试将Thread.Sleep(1000)放入循环中。 像上面提到的那样,文件并不总是及时发布,以便循环的下一次迭代。

正如其他人所说,反复打开和关闭文件可能是个问题。 未提及的一个解决方案是在处理期间保持文件打开。 完成后,可以关闭该文件。

佩德罗:

正如其他人所说,反复打开和关闭文件可能是个问题。 未提及的一个解决方案是在处理期间保持文件打开。 完成后,可以关闭该文件。

或者,或者,在StringBuilder或其他内存中的文本存储中收集文本,然后在循环结束后将文本转储到文件中。

我遇到类似的问题时发现了这个post。 给出的建议给了我一个想法! 所以为此我编写了以下方法

 public static void ExecuteWithFailOver(Action toDo, string fileName) { for (var i = 1; i <= MaxAttempts; i++) { try { toDo(); return; } catch (IOException ex) { Logger.Warn("File IO operation is failed. (File name: {0}, Reason: {1})", fileName, ex.Message); Logger.Warn("Repeat in {0} milliseconds.", i * 500); if (i < MaxAttempts) Thread.Sleep(500 * i); } } throw new IOException(string.Format(CultureInfo.InvariantCulture, "Failed to process file. (File name: {0})", fileName)); } 

然后我用以下方式使用了该方法

  Action toDo = () => { if (File.Exists(fileName)) File.SetAttributes(fileName, FileAttributes.Normal); File.WriteAllText( fileName, content, Encoding.UTF8 ); }; ExecuteWithFailOver(toDo, fileName); 

后来我分析了日志,我发现我遇到麻烦的原因是试图对并行线程中的同一个文件进行操作。 但我仍然看到一些使用建议的FailOver方法的专业人士

尝试在文件操作周围使用锁定。 http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx