2

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

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

私はコードを添付しています。どんな助けでも大歓迎です、ありがとう。

namespace Copier

{ public 部分クラス Form1 : Form { public 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);
        }
    }
}

または、フォームがフリーズしていないことを示すように、進行状況バーを自動的に表示する方法を誰かに教えてもらえますか?

コードをクリーンアップしました

これまでの入力に感謝します

4

3 に答える 3

3

ファイルがコピーされたときに OS から更新を取得できるように、進行状況ハンドラーを指定できる CopyFileEx を呼び出すのが最も簡単だと思います。以下は、 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;
}
于 2012-05-09T15:20:35.347 に答える
2

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

于 2012-05-09T14:19:45.130 に答える
0

私の提案は、DoWork バックグラウンド ワーカーのコンテンツを移動し、それぞれに分離してから、バックグラウンド ワーカーをトリガーするために使用btnCopyTo_Clickすることです。バックグラウンドワーカーを使用して進行状況を報告できるため、それを行わずに開始することさえできません.btnCopyFrom_ClickbtnCopyTo_ClickbtnCopyFrom_Click

プログレス バーを実際に更新するタイミングについては、コピーするファイルのサイズを毎回確認することをお勧めします。

次に、ファイルを特定のサイズのブロックに分割し、ループを使用して一度に 1 つのブロックをコピーすると、ループのサイクル数に関係なく、進行状況バーを特定の量だけインクリメントできるはずです。

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

于 2012-05-09T14:32:10.680 に答える