12

私は 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;
        }

ファイルが実際に宛先に到達することを確認する方法を誰か教えてもらえますか? -- 移動するファイルは非常に大きい可能性があります -- (最大 2 時間のフル HD mp4 ファイル)

ありがとう!

4

6 に答える 6

9

ストリームを使用し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/Await 構文を使用するためにAsync CTPをインストールする必要があります

于 2013-01-04T20:32:31.727 に答える
1

ファイルが元のディレクトリから消えるのを監視し、それらが実際にターゲットディレクトリに表示されていることを確認できます。

私はファイルウォッチャーで素晴らしい経験をしていません。別のスレッドまたはタイマーが実行されている間、移動を実行しているスレッドにAutoResetEventを待機させて、ファイルが元の場所から消えることを定期的にチェックし、ファイルが新しい場所にあることを確認します。ニーズ)ファイルの整合性チェック(MD5チェックなど)を実行します。これらの条件が満たされると、「チェッカー」スレッド/タイマーがAutoResetEventをトリガーして、元のスレッドが進行できるようにします。

「チェッカー」に「これには時間がかかりすぎています」というロジックを含めます。

于 2013-01-04T18:48:57.220 に答える
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
于 2013-01-04T20:13:51.213 に答える
0

アプリケーションの実行を何時間も停止しないように、移動を別のスレッドで実行することをお勧めします。

移動が完了しないとプログラムを続行できない場合は、ダイアログを開いて移動スレッドを定期的にチェックインし、進行状況トラッカーを更新できます。これにより、ユーザーにフィードバックが提供され、プログラムがフリーズしたように感じることがなくなります。

ここに情報と例があります:http: //hintdesk.com/c-wpf-copy-files-with-progress-bar-by-copyfileex-api/

于 2013-01-04T19:24:01.347 に答える
0

コピーされたファイルサイズが元のファイルのファイルサイズに達したかどうかをバックグラウンドタスクで定期的にチェックしてみてください(ファイル間で比較するハッシュを追加できます)

于 2013-01-04T20:55:20.240 に答える
0

最近同様の問題が発生しました。

OnBackupStarts();
//.. do stuff

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


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

待機せず、イベントに反応する

于 2013-01-04T21:33:02.567 に答える