2012-05-09 18 views
2

ある場所から別の場所にファイルをコピーしているときに進行状況バーを更新する方法を探しています。大きなファイルをコピー中に進行状況バーを更新する

私はBackgroundWorkerでコピーを行い、バックグラウンドでも進行状況バーを更新しています。私はfile.lengthを使用してファイルサイズを取得し、パーセンテージを使用してバーをそのように更新しましたが、喜んでは使用しませんでした。

私はコードを添付しており、何か助けていただければ幸いです。ありがとうございます。

namespace Copier 

{パブリック部分クラスをForm1:フォーム {公共のForm1(){ のInitializeComponent(); }

// Declare for use in all methods 
    public string copyFrom; 
    public string copyTo; 

    private void btnCopyFrom_Click(object sender, EventArgs e) 
    { 
     // uses a openFileDialog, openFD, to chose the file to copy 
     copyFrom = ""; 

     openFD.InitialDirectory = @"C:\Documents and Settings\user\My Documents"; 
     openFD.FileName = ""; 

     //openFD.ShowDialog(); 

     if (openFD.ShowDialog() == DialogResult.Cancel) 
     { 
      MessageBox.Show("cancel button clicked"); 
     } 

     else 
     { 
      // sets copyFrom = to the file chosen from the openFD 
      copyFrom = openFD.FileName; 
      // shows it in a textbox 
      txtCopyFrom.Text = copyFrom; 
     } 
    } 

    private void btnCopyTo_Click(object sender, EventArgs e) 
    { 
     //uses folderBrowserDialog, folderBD, to chose the folder to copy to 
     copyTo = ""; 

     this.folderBD.RootFolder = System.Environment.SpecialFolder.MyComputer; 
     this.folderBD.ShowNewFolderButton = false; 
     //folderBD.ShowDialog(); 
     //DialogResult result = this.folderBD.ShowDialog(); 

     if (folderBD.ShowDialog() == DialogResult.Cancel) 
     { 
      MessageBox.Show("cancel button clicked"); 
     } 
     else 
     { 
      // sets copyTo = to the folder chosen from folderBD 
      copyTo = this.folderBD.SelectedPath; 
      //shows it in a textbox. 
      txtCopyTo.Text = copyTo; 
     } 
    } 

    private void btnCopy_Click(object sender, EventArgs e) 
    { 
     copyBGW.RunWorkerAsync(); 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     Application.Exit(); 
    } 

    //================================================================= 
    //      BackGroundWorkers 
    //================================================================= 

    private void copyBGW_DoWork(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      // copies file 
      string destinatationPath = Path.Combine(copyTo, Path.GetFileName(copyFrom)); 
      File.Copy(copyFrom, destinatationPath); 
      MessageBox.Show("File Copied"); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 
} 

それとも誰かが私にちょうどそれがフォームが凍結していないことを示しているように、プログレスバーが自己で行くようにする方法を示すことができましたか?

は、これまで

+3

http://stackoverflow.com/questions/187768/can-i-show-file-copy-progress-using-fileinfo-copyto -in-net –

+0

補足として、この[チュートリアル](http://www.albahari.com/threading/part3.aspx#_BackgroundWorker)をBackgroundWorkerスレッドで読むことをお勧めします。BackgroundWorkerスレッドの 'RunWorkerCompleted'イベントに' MessageBox.Show'や例外処理のようなコードを置きます。 –

答えて

2

これは、複数のレベルで作業することはできませんコードに入力用

感謝をクリーンアップしています。まず第一に、バックグラウンドワーカーはWorkerReportsProgressで「変更を報告」する必要がありますが、このフラグは彼が自動的に行うことはできませんが、もちろん動作しません。そのため、ワーカーはメソッドReportProgressを提供して、現在の進行状況を表示するためにそのメソッドを呼び出す必要があります。そして、これはあなたのアプローチの最終的な欠陥を明らかにします。 File.Copyメソッドはブロックされていますが、作業者はReportProgressメソッドを呼び出す時間が必要です。したがって、ファイルを非同期でコピーする方法を見つける必要があります。 This質問が役に立つかもしれませんが、もちろんDave Bishsのコメントは非同期ファイルのコピーの参考になります。

+1

ファイルをコピーして進捗状況を報告する方法の他の例を次に示します:http://stackoverflow.com/a/6055385/519244、BackgroundWorkerのDoWorkイベントハンドラはCopyメソッドと似ていて、OnProgressChangedコールをBackgroundWorkerのReportProgressメソッドへの呼び出しです。 –

+0

@ Renaud Dumontストリームを使って独自のコピーメソッドを作成するのが賢明かどうかは分かりません。私は、実際のコピー方法は、この種のio操作にはるかに効率的だと思うでしょうが、私はそのための参照はありません。しかし、実際のコピーで何らかの最適化が行われていれば、その非同期バージョンが存在しない可能性があります。 – dowhilefor

+0

まず入力のおかげで。私は世界のgreatesプログラマーではなく、1〜2週間前に学習したC#を始めただけです。私は最初のコードが少しばかげたエラーでいっぱいだったことを知っています、私はそれらを試して、私がしようとしていたことを示すのを助けるために入れます。私は 'progressBar1.Style = ProgressBarStyle.Marquee;'を使用しています。プログラムがフリーズしていないことと、ファイルがコピーおよびコピーされているときに変更されるラベルが表示されます。もう一度、入力していただきありがとうございます。私のソリューションは、私が尋ねたことから非常に愚かになりましたが、私は非同期で十分に頭を上げることはできません。ありがとう – ELSheepO

0

私の提案は、それぞれについて別個DoWork背景労働者にbtnCopyTo_ClickbtnCopyFrom_Clickの内容を移動した後、バックグラウンドワーカーをトリガするbtnCopyTo_ClickbtnCopyFrom_Clickを使用することであろう。バックグラウンドワーカーは進捗状況を報告するために使用することができます。

プログレスバーを実際に更新する時期は、コピーするファイルのサイズを毎回決めることをおすすめします。

ファイルを特定のサイズのブロックに分割し、ループを使用して一度に1ブロックをコピーすると、ループの多くのサイクルで一定の量だけプログレスバーを増やすことができます。

また、コピーが行われている間にプログレスバーを0から100まで連続的にループする非同期スレッドを持つ方法を見つけることもできます。かなり基本的な解決策ですが、少なくとも、何かが起こっていることをユーザーに知らせることができます。

3

CopyFileExを呼び出すだけで、ファイルがコピーされるときにOSからの更新を取得できるように、進捗ハンドラを指定するのが最も簡単だと思います。ここでCopyFileExためpinvoke.netページからコピーされたサンプルコードは次のとおりです。

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName, 
    CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel, 
    CopyFileFlags dwCopyFlags); 

delegate CopyProgressResult CopyProgressRoutine(
long TotalFileSize, 
long TotalBytesTransferred, 
long StreamSize, 
long StreamBytesTransferred, 
uint dwStreamNumber, 
CopyProgressCallbackReason dwCallbackReason, 
IntPtr hSourceFile, 
IntPtr hDestinationFile, 
IntPtr lpData); 

int pbCancel; 

enum CopyProgressResult : uint 
{ 
    PROGRESS_CONTINUE = 0, 
    PROGRESS_CANCEL = 1, 
    PROGRESS_STOP = 2, 
    PROGRESS_QUIET = 3 
} 

enum CopyProgressCallbackReason : uint 
{ 
    CALLBACK_CHUNK_FINISHED = 0x00000000, 
    CALLBACK_STREAM_SWITCH = 0x00000001 
} 

[Flags] 
enum CopyFileFlags : uint 
{ 
    COPY_FILE_FAIL_IF_EXISTS = 0x00000001, 
    COPY_FILE_RESTARTABLE = 0x00000002, 
    COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004, 
    COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008 
} 

private void XCopy(string oldFile, string newFile) 
{ 
    CopyFileEx(oldFile, newFile, new CopyProgressRoutine(this.CopyProgressHandler), IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE); 
} 

private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long StreamByteTrans, uint dwStreamNumber,CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData) 
{ 
    return CopyProgressResult.PROGRESS_CONTINUE; 
} 
+0

技術的にはこれは依然として呼び出し元のスレッドをブロックしますが、ファイルのコピーやキャンセル、「再起動」の動作(これは慎重になる可能性があります)から進捗状況を得る良い方法です。しかし、ええと、FileCopyEXを呼び出すと、コピーが終了するか、キャンセルされるまで、呼び出しスレッドがブロックされます。ただし、フォームの進行状況バーを更新することはできません。 – TCC

関連する問題