【问题标题】:Exception when moving a file 3 times移动文件 3 次时出现异常
【发布时间】:2014-08-21 19:53:03
【问题描述】:

当我将同一个文件 3 次复制到文件夹 A 中时,为什么我得到一个 IOException(该进程无法访问该文件,因为它正在被另一个进程使用。)?

class FileWatcher {

    FileSystemWatcher fsw;
    FileInfo file;
    string destination = @"C:\FileMover\B\";
    Random random;

    public FileWatcher() {
        fsw = new FileSystemWatcher();
        random = new Random();           

        fsw.Path = @"C:\FileMover\A";

        fsw.Created += fsw_Created;

        fsw.EnableRaisingEvents = true;
    }

    void fsw_Created(object sender, FileSystemEventArgs e) {            
        string destinationFileName = destination + e.Name;

        if (!File.Exists(destinationFileName)) {
            file = new FileInfo(e.FullPath);
            file.MoveTo(destinationFileName);
        }
        else {
            file = new FileInfo(e.FullPath);                
            file.MoveTo(destinationFileName + random.Next());
        }
        file = null;                       
    }  
}

主要:

class Program {      
    static void Main(string[] args) {

        FileWatcher watcher = new FileWatcher();

        while (Console.ReadKey().Key != ConsoleKey.Q) {

        }
    }
}

2次后文件夹B包含2个文件(sourceFileName和sourceFileName1274968236)

当我调试该部分时,不会抛出异常。

【问题讨论】:

  • 我无法复制此文件 - 我可以多次粘贴文件并且不会引发异常。你每次都得到例外吗?你在哪个平台上运行?
  • 是的,我每次都遇到异常。我正在运行 Windows 8.1 专业版。当我关闭我的程序并重新启动它时,我会在将相同的文件复制到文件夹 A 后立即得到异常。

标签: c#


【解决方案1】:

Created 可能会在文件刷新 (?) 到目标之前引发。尝试使用Changed 并检查e.ChangeType==WatcherChangeTypes.Created

参考:http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created(v=vs.110).aspx

编辑: Changed 事件在 Created 之后引发,如果这是由于竞争条件,可能会有所帮助,但问题仍然可能发生。

创建文件后立即引发 OnCreated 事件。如果一个文件 正在被复制或传输到监视目录中,OnCreated 事件将立即引发,然后是一个或多个 OnChanged 事件。

找到这个:Wait Until File Is Completely Written 还有这个:Is there a way to check if a file is in use?

【讨论】:

  • Wait Until File Is Completely Written 中接受的答案帮助了我。我会做更多的测试,然后将其标记为答案。还要感谢 LaMMMy
  • 现在一切正常。最重要的提示是使用 Changed Event 而不是 Created。
【解决方案2】:

使用来自@celerno 的提示和他分享的链接,这是我发现的工作:

    public FileWatcher()
    {
        fsw = new FileSystemWatcher();
        random = new Random();

        fsw.Path = @"C:\FileMover\A";

        fsw.Created += fsw_Created;
        fsw.Changed += fsw_Created;

        fsw.EnableRaisingEvents = true;
    }

并将 fsw_Created 更改为:

        if(!IsFileLocked(fi)){
            if (!File.Exists(destinationFileName))
            {
                fi = new FileInfo(e.FullPath);
                fi.MoveTo(destinationFileName);
            }
            else
            {
                fi = new FileInfo(e.FullPath);
                string fileName = destinationFileName + random.Next();
                fi.MoveTo(fileName);
            }
            fi = null;
        }

IsFileLocked 直接取自@celerno 提到的the link

我删除了该文件的许多副本,但它从未抛出异常。我猜Changed 事件在文件被释放后立即发生,否则,如果它在尝试移动时被锁定,则 Created 永远不会被调用,所以文件就在那里。在这种情况下,您似乎需要两者。

我只是想编辑以添加异常似乎仅在您将同名文件一次又一次复制到源目录时引发。猜测该文件名的锁定只需要释放,然后您就可以复制另一个具有相同名称的文件。

【讨论】:

  • 竞争条件通常很难或不可能从一台计算机准确地复制到另一台计算机,这就是为什么我没有费心重现该问题的原因。此外,助手 IsFileLocked 并非 100% 安全,请参阅此评论:stackoverflow.com/questions/876473/…
  • 我确实看到了那条评论。我意识到竞争条件是不可预测的,但是我能够重现它并假设没有其他东西正在使用该解决方案可用的文件。我猜必须采取保护措施以确保覆盖其他文件锁定来源。
猜你喜欢
  • 1970-01-01
  • 2019-09-08
  • 2018-04-14
  • 1970-01-01
  • 2021-02-02
  • 2013-05-30
  • 2016-10-02
  • 2015-03-27
  • 1970-01-01
相关资源
最近更新 更多