System.IO.File.Move - 如何等待移动完成?

时间:2013-01-04 18:44:18

标签: c# wpf

我正在用c#编写一个WPF应用程序,我需要移动一些文件 - 我真的需要知道文件是否成功。为此,我编写了一个检查,确保文件在移动后到达目标目录 - 问题是有时我会在文件完成移动之前进行检查:

   System.IO.File.Move(file.FullName, endLocationWithFile);

            System.IO.FileInfo[] filesInDirectory = endLocation.GetFiles();
            foreach (System.IO.FileInfo temp in filesInDirectory)
            {
                if (temp.Name == shortFileName)
                {

                    return true;
                }
            }

            // The file we sent over has not gotten to the correct   directory....something went wrong!
            throw new IOException("File did not reach destination");

        }
        catch (Exception e)
        {
            //Something went wrong, return a fail;
            logger.writeErrorLog(e);
            return false;
        }

有人可以告诉我如何确保文件实际到达目的地吗? - 我将要移动的文件可能非常大 - (全高清mp4文件长达2小时)

谢谢!

6 个答案:

答案 0 :(得分:8)

您可以使用Aysnc Await的流来确保文件完全复制

这样的事情应该有效:

private void Button_Click(object sender, RoutedEventArgs e)
{
    string sourceFile = @"\\HOMESERVER\Development Backup\Software\Microsoft\en_expression_studio_4_premium_x86_dvd_537029.iso";
    string destinationFile = "G:\\en_expression_studio_4_premium_x86_dvd_537029.iso";

    MoveFile(sourceFile, destinationFile);
}

private async void MoveFile(string sourceFile, string destinationFile)
{
    try
    {
        using (FileStream sourceStream = File.Open(sourceFile, FileMode.Open))
        {
            using (FileStream destinationStream = File.Create(destinationFile))
            {
                await sourceStream.CopyToAsync(destinationStream);
                if (MessageBox.Show("I made it in one piece :), would you like to delete me from the original file?", "Done", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    sourceStream.Close();
                    File.Delete(sourceFile);
                }
            }
        }
    }
    catch (IOException ioex)
    {
        MessageBox.Show("An IOException occured during move, " + ioex.Message);
    }
    catch (Exception ex)
    {
        MessageBox.Show("An Exception occured during move, " + ex.Message);
    }
}

如果您使用VS2010,则必须安装Async CTP才能使用新的Async / Await语法

答案 1 :(得分:1)

您可以观察文件从原始目录中消失,然后确认它们确实出现在目标目录中。

我对文件观察者没有很好的经验。我可能会让线程执行移动等待AutoResetEvent,而单独的线程或计时器运行以定期检查文件是否从原始位置消失,检查它们是否在新位置,并且可能(取决于根据您的环境和需求)对文件执行一致性检查(例如,MD5检查)。一旦满足这些条件,“checker”线程/计时器将触发AutoResetEvent,以便原始线程可以进行。

在“检查器”中加入一些“这是太长时间”的逻辑。

答案 2 :(得分:1)

为什么不通过复制流来管理自己的副本?

//http://www.dotnetthoughts.net/writing_file_with_non_cache_mode_in_c/
const FileOptions FILE_FLAG_NO_BUFFERING = (FileOptions) 0x20000000;

//experiment with different buffer sizes for optimal speed
var bufLength = 4096;

using(var outFile = 
    new FileStream(
        destPath,
        FileMode.Create, 
        FileAccess.Write, 
        FileShare.None, 
        bufLength, 
        FileOptions.WriteThrough | FILE_FLAG_NO_BUFFERING))
using(var inFile = File.OpenRead(srcPath))
{
    //either
    //inFile.CopyTo(outFile);

    //or
    var fileSizeInBytes = inFile.Length;
    var buf = new byte[bufLength];
    long totalCopied = 0L;
    int amtRead;
    while((amtRead = inFile.Read(buf,0,bufLength)) > 0)
    {
        outFile.Write(buf,0,amtRead);
        totalCopied += amtRead;
        double progressPct = 
            Convert.ToDouble(totalCopied) * 100d / fileSizeInBytes;
        progressPct.Dump();
    }
}
//file is written

答案 3 :(得分:0)

您很可能希望移动发生在一个单独的线程中,这样您就不会在几个小时内停止执行您的应用程序。

如果程序无法在没有完成移动的情况下继续,那么您可以打开一个对话框并定期检查移动线程以更新进度跟踪器。这为用户提供了反馈,并且可以防止他们感觉好像程序已经冻结。

这里有信息和示例: http://hintdesk.com/c-wpf-copy-files-with-progress-bar-by-copyfileex-api/

答案 4 :(得分:0)

尝试在后台任务中定期检查是否复制了文件 size达到原始文件的文件大小(您可以添加文件之间的哈希比较)

答案 5 :(得分:0)

最近遇到了类似的问题。

OnBackupStarts();
//.. do stuff

 new TaskFactory().StartNew(() =>
                {
                    OnBackupStarts()
                    //.. do stuff
                    OnBackupEnds();
                });


void OnBackupEnds()
    {
        if (BackupChanged != null)
        {
            BackupChanged(this, new BackupChangedEventArgs(BackupState.Done));
        }
    }

不要等待,对事件做出反应