【问题标题】:FileSystemWatcher: System.IO.IOException ("File used by another process")FileSystemWatcher:System.IO.IOException(“文件被另一个进程使用”)
【发布时间】:2018-03-29 08:26:02
【问题描述】:

目前我正在开发一个应用程序,它应该监视特定目录的更改(例如创建了一个新文件),然后将文件上传到 Sharepoint。在那之前,我正在使用 FileSystemWatcher 类,它会抛出一个带有创建文件路径的事件,而我又在另一种方法中使用它来上传文件。问题是:在 Visual Studio 的调试模式下,我意识到我在监视目录中创建的第一个文件被完美上传,即使我一次将多个文件拖到目录中,所有文件都被上传了,但是当我在之后执行一个文件时另一个我得到一个例外,第二个文件已经在使用中。因此,我将 File1.txt 拖到目录中,它可以工作,但是,当我在尝试创建要上传到 Sharepoint 的文件流并告诉我 file2 时收到 System.IO.IOException 后立即将 file2.txt 拖到目录中时。 txt 正被另一个进程使用。

FileSystemWatcher 的代码:

 public void StartWatcher()
        {
            FileSystemWatcher fsw = new FileSystemWatcher(this.path);

            fsw.IncludeSubdirectories = true;

            fsw.EnableRaisingEvents = true;



            fsw.Created += new FileSystemEventHandler(CreateFile);


            try
            {

                while (true)
                {
                    fsw.WaitForChanged(WatcherChangeTypes.All);
                }
            }
            catch
            { }

                fsw.EnableRaisingEvents = false;

        }

调用的 CreateFile() 方法

fsw.Created += new FileSystemEventHandler(CreateFile);

看起来像这样:

 private void CreateFile(object sender, FileSystemEventArgs e)
        {
            path = String.Format(e.FullPath);
            filename = Path.GetFileName(path);
            Stream fs = File.OpenRead(@path);
            SPAPI spobj = new SPAPI();
            spobj.SPUploader(fs, filename);
            fs.Close();
        }

异常被抛出

Stream fs = File.OpenRead(@path);

但仅当第二个文件被拖入第一个文件之后的目录时。奇怪的是,不是第一个文件正在使用,而是第二个我想作为流打开。所以它不是仍然打开并导致异常的流。似乎 FileSystemWatcher 正在使用第二个文件。但是为什么第一个文件可以正常工作,但是当第二个文件被拖入目录时却抛出异常?

【问题讨论】:

  • fsw.WaitForChanged(WatcherChangeTypes.All); - 放弃这个。以及围绕它的可恶循环,包括 empty 捕获。
  • 文件创建事件引发并立即触发您在监视目录中创建的CreateFile 新文件。但是,您将文件拖放到目录中并不意味着您可以使用该文件,因为文件可能仍在复制到目录中。如果你的文件大小是标准的并且你知道复制/创建操作需要多少时间,你可以在path = String.Format(e.FullPath);之前添加Thread.Sleep()
  • 休息一下再试一次。在过去每次延迟 100 毫秒后,我已经成功重试了 3 次。
  • 这是意料之中的事件。您应该期待并处理它(如果您遇到此错误 - 请稍等,然后重试)。
  • @Mondblut 请注意,Thread.Sleep(100) 不是非常可靠的解决方案。尝试将 1GB 文件复制到您的文件夹中,您会看到它会如何以 Thread.Sleep(100) 失败。

标签: c# ioexception filesystemwatcher


【解决方案1】:

你可以这样修改和使用。希望对你有帮助

private void CreateFile(object sender, FileSystemEventArgs e)
{
    int until = 5;
    int i = 0;
    bool success = false;
    while (!success && i < until)
    {
        try
        {
            path = String.Format(e.FullPath);
            filename = Path.GetFileName(path);
            using (Stream fs = File.OpenRead(@path);)
            {
                SPAPI spobj = new SPAPI();
                spobj.SPUploader(fs, filename);
            }
            success = true;
        }
        catch
        {
            i++;
            Thread.Sleep(TimeSpan.FromSeconds(1));
        }
    }
}

【讨论】:

  • 这就像一个魅力,我只是添加了 fs.Close() 来关闭文件流。
  • 像其他用户建议的那样使用 Thread.Sleep(100) 有什么好处吗?
  • Thread.Sleep(TimeSpan.FromSeconds(1)); or Thread.Sleep(TimeSpan.FromMilliseconds(1000)); or Thread.Sleep(1000) 无所谓。
  • try-catchuntil 参数提供了一些灵活性,如果您的文件大小不同且范围很大。您可以编辑尝试计数和等待时间。例如:如果文件大小在 1x 和 3x 之间,可以使用 until=3 和 waitResponse=t;如果文件大小介于 2x 和 8x 之间,您可以使用 until=4 和 waitResponse = 2t。结果,任务根据文件大小消耗时间。
猜你喜欢
  • 2011-04-13
  • 2017-12-02
  • 2011-09-04
  • 2012-04-24
  • 1970-01-01
  • 2016-12-24
相关资源
最近更新 更多