【问题标题】:File is being used by another process文件正被另一个进程使用
【发布时间】:2011-04-13 20:09:32
【问题描述】:

我有一个大致可以做到这一点的程序:

  1. 打开要读取的文件。
  2. 关闭文件
  3. 启动文件监视程序以监视文件中的更改。
  4. 一旦检测到更改,文件监视器的 EnableRaisingEvents 标志就会设置为 false,并且该过程从步骤 1 开始重复。

问题是,从第 4 步转到第 1 步后,它无法读取文件说它正在被另一个进程使用。

我收到错误:

未处理的异常:System.IO.IOException:进程无法访问文件“c:\test.xml”,因为它正被另一个进程使用。

怎么了?我的程序第 1 步中的阅读器是否仍然打开文件,或者是访问文件的完全不同的进程,还是文件观察器在从第 4 步移到第 1 步后仍在观看文件,尽管将标志设置为 false?

【问题讨论】:

  • 你能发布你的代码吗?这可能有助于我们回答您的问题。
  • 发布一些代码。帮助我们帮助您。
  • 代码有点庞大和机密,因为它是给一家金融公司的,但我会看看我是否可以让它安全并发布它。
  • 也许你应该发布一些代码(只是打开和关闭文件的部分)。也许您的程序仍然打开文件,或者 FileWatcher 仍然打开。
  • 很可能您的步骤 1 中的代码保持文件锁定,我会先看看那里

标签: c#


【解决方案1】:

问题在于 FileSystemWatcher 会立即告诉您文件何时创建。它不会等待文件被释放。 例如,当您复制一个需要 3 秒才能复制的大文件时,您必须在此之后打开该文件。

http://www.codeproject.com/Questions/461666/FileSystemWatcher-issue-in-windows-application Wait until file is unlocked in .NET

【讨论】:

    【解决方案2】:

    您可以使用此 MS 实用程序openfiles 获取已打开文件的列表并了解谁打开了该文件。

    openfiles /query
    

    它还允许断开网络用户打开的文件。

    openfiles /disconnect /id XXXX
    

    如果你想在本地 PC 上使用它,你应该设置维护对象列表全局标志:

    openfiles /local on
    

    关注link了解更多详情。

    【讨论】:

      【解决方案3】:

      注意:即使“file.txt”在记事本中打开,这段代码仍然有效,因为它是打开读取的。

      using System;
      using System.IO;
      
      class Program
      {
        static void Main(string[] args)
        {
          ReadFromFile(@"C:\file.txt");
          Console.ReadLine();
        }
      
        static void ReadFromFile(string filename)
        {
          string line;
          using (StreamReader sr = File.OpenText(filename))
          {
            line  = sr.ReadLine();
            while (line != null)
            {
              Console.WriteLine(str);
              line = sr.ReadLine();
            }
            sr.Close();
          }
        }
      }
      

      或者只是:

      string text = System.IO.File.ReadAllText(@"C:\file.txt");

      【讨论】:

        【解决方案4】:

        除了其他答案之外,当FileWatcher 反应文件时,它可能尚未被该应用程序关闭。在第 1 步中尽量不要立即失败,而是尝试几次尝试,并稍有延迟。

        【讨论】:

          【解决方案5】:

          如果你的代码类似这样:

          [STAThread]
          static void Main(string[] args)
          {
              string file = "temp.txt";
              ReadFile(file);
              FileSystemWatcher fswatcher = new FileSystemWatcher(".\\");
              fswatcher.Changed += delegate(object sender, FileSystemEventArgs e)
                                       {
                                           ReadFile(e.FullPath);
                                       };
              while (true)
              {
                  fswatcher.WaitForChanged(WatcherChangeTypes.Changed);
              }
          }
          private static void ReadFile(string file)
          {
              Stream stream = File.OpenRead(file);
              StreamReader streamReader = new StreamReader(stream);
              string str = streamReader.ReadToEnd();
              MessageBox.Show(str);
              streamReader.Close();
              stream.Close();
          }
          

          如果您通过记事本编辑文件,那么当您单击保存按钮时,文件会保持打开状态,而就像您关闭程序并单击保存时一样。我不知道这是记事本的错误还是未记录的功能,但这可能是您的问题。解决此问题的一种方法是执行以下操作:

          在您的匿名委托中,或在您执行对ReadFile() 的调用的任何位置调用Thread.Sleep(1000),让程序在读取文件之前等待,您的代码应该可以正常工作。

          【讨论】:

          • @xbonez:即使没有Thread.Sleep(),这段代码对我来说也能正常工作。 (我将MessageBox.Show 更改为Console.WriteLine)但是,我仍然会使用using 语句。
          • 玩了一会儿之后,我发现如果我有两个该程序的实例正在观看同一个文件,当我在记事本中单击“保存”时,我会从其中一个实例中收到此错误(另一个继续运行):The process cannot access the file 'c:\file.txt' because it is being used by another process.
          • 在进一步搞砸之后,有时即使只运行了一个观察程序副本,我也会收到The process cannot access the file 错误。因此,我在ReadFile(e.FullPath) 之前将Thread.Sleep(500) 放在delegate 中,现在效果很好。我现在有一个强大的小文件观察程序:+1 Richard :)
          【解决方案6】:

          可能会发生很多事情。

          首先,通过在实现IDisposable 的所有内容周围使用 using 子句,确保正确处理文件编写器(关闭还不够好)。

          其次,您只是在阅读,请确保在打开文件时设置了正确的标志。

          如果您提供了一个代码块来说明您是如何完成此任务的,那么这将有所帮助;特别是在阅读文件时

          【讨论】:

            【解决方案7】:

            您可以使用http://www.sysinternals.com 中的 Process Explorer 之类的工具来查看谁拥有该进程的打开句柄

            文件很可能是因为最初触发更改通知的原因而保持打开状态。

            【讨论】:

              猜你喜欢
              • 2016-12-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多