2

実行可能ファイルを実行する前に、.NET 4 を使用して更新をチェックする (かなり) シンプルな C# アプリケーションを作成しています。新しいバージョンの exe がネットワーク共有に存在する場合は、それをローカル フォルダーにコピーして起動します。File.Copy() の制限について読んでいる間を除いて、すべて完全に機能しています。これを行っている間は進行状況バーを表示できないことに気付きました。私はそれをしようとしています。

ここにあるサンプル コードを使用したところ、正常にコンパイルされました (ただし、backgroundworker がどのように機能するのか正確にはまだ少しわかりません)。ただし、実際にアプリケーションを実行しようとすると、CopyFilEx() メソッドは false を返します。エラーは「パラメータが正しくありません」です。

私のコード (関連するセクションのみ、必要に応じて追加します)

関数の呼び出し:

XCopy.Copy(strServerAppPath + strExeName, strLocalAppPath + strExeName, true, true, (o,    pce) =>
{
worker.ReportProgress(pce.ProgressPercentage, strServerAppPath + strExeName);
});

(ソース パスは "C:\test.txt" と評価され、宛先パスは "C:\test\test.txt" と評価されます)

上記のリンクのコードでエラーが発生する場所:

bool result = CopyFileEx(Source, Destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags);
            if (!result)
                throw new Win32Exception(Marshal.GetLastWin32Error());

助けてくれてありがとう、私はこれに数時間苦労してきました...

4

2 に答える 2

3

すべてのマーシャリングを処理するのではなく、チャンクごとに「独自の」コピー機を作成するのは非常に簡単です。

private static void CopyFile(string source, string destination, int bytesPerChunk)
{
    int bytesRead = 0;

    using (FileStream fs = new FileStream(source, FileMode.Open, FileAccess.Read))
    {
        using (BinaryReader br = new BinaryReader(fs))
        {
            using (FileStream fsDest = new FileStream(destination, FileMode.Create))
            {
                BinaryWriter bw = new BinaryWriter(fsDest);
                byte[] buffer;

                for (int i = 0; i < fs.Length; i += bytesPerChunk)
                {
                    buffer = br.ReadBytes(bytesPerChunk);
                    bw.Write(buffer);
                    bytesRead += bytesPerChunk;
                    ReportProgress(bytesRead, fs.Length);  //report the progress
                }
            }
        }
    }
}
于 2012-04-27T16:51:52.383 に答える
3

呼び出しごとにReadBytes()新しいバッファ配列を割り当てるを呼び出す代わりに、(たとえば 64KB のサイズの) 1 つのバッファを割り当てて を呼び出します。これは最大バイト数を配列に読み取り、読み取った実際のバイト数を返します。次に、読み取りごとに同じバッファ配列を再利用します (その内容をターゲット ストリームに書き出した後)。これにより、読み取り/書き込み操作ごとに新しいバッファーを再割り当てする必要がなくなります。byte[]Read(buf, 0, buf.Length)buf.Length

たとえば、ストリーム コピー メソッドの内部ループは次のようになります。

byte[]  buf;

// Allocate an I/O data buffer
buf = new byte[64*1024];

// Copy the contents of the input stream to the output stream
for (;;)
{
    int     len;

    // Read a block of data from the input stream
    len = inp.ReadBytes(buf, 0, buf.Length);
    if (len <= 0)
        break;

    // Write the data to the output stream
    outp.Write(buf, 0, len);
}

ループは、最大 64KB のバイトを入力ストリームからバッファーに読み取り、読み取った実際のバイト数を出力ストリームに書き込みます。各読み取り/書き込み操作に同じバッファーが使用されるため、不要なバッファーの割り当てと割り当て解除は行われません。読み取り操作が失敗すると、入力ストリームの最後に到達したので、ループを終了します。

于 2014-06-03T21:08:27.720 に答える