クライアントとサーバーのファイルを比較する役割を持つc#patcherを開発しています。矛盾があると自動的にダウンロードされます。
これはWPFアプリケーションで、プログレスバーを更新しながら複数の非同期ダウンロードを処理するために、私はネット4.5の非同期/待機を使用しました。
これは完全に動作しますが、同じアプリケーションをWindows XP上で実行する必要があります。また、BackgroundWorkerを使用してすべてのコードをリファクタリングすることにしました。これはネット4でもサポートされています。
プロセス中にファイルをランダムに飛び越します。
問題は、最初のファイル(特定のファイル)がダウンロードされていないことです。
3つの異なるファイルがダウンロードされたような場合、問題のあるファイルが例えば2番目の場合は最初のダウンロードが開始されましたが、ほとんどの場合3番目のファイルにジャンプして2番目のファイルのサイズは0KBになりました。
問題のあるファイルが最初または最後の場合、結果は同じでした。それはプログラムが好きではなかったようだった。
変更があってもうまくいきませんでしたが、初期のコードに戻って、すべての作業をロールバックすることにしました。
さて、私は問題はなく、すべてのファイルが正しくダウンロードされていますが、楽しいことは、同じ実行可能ファイルを別の人に与えると、私は同じ問題が残っていることです。
どのように可能かはわかりませんが、このファイルは他のファイルとまったく同じです。
ソフトウェアのいくつかの他の情報:開始時
、プログラムチェックすべてのファイルが更新されたファイルのすべてのMD5ハッシュを持つファイルでそれらのそれぞれのMD5ハッシュを比較し、同じであれば、 (前にPHPスクリプトで生成)。
ダウンロードするファイルがある場合、プログラムはウィンドウにファイルを挿入し、最後にHTTPDownloaderに挿入します(ある場合)。
HTTPDownloadは、forループを使用してすべてのファイルをダウンロードし始めます。パラレルI/O操作が行われていないことを確認するためにclient.isBusyが呼び出されます。
WebClientのすべてのイベントといくつかのカスタムをリスンするDownloadListenerがあります。イベントは別のスレッド(HTTPDownloaderによる)で発生するため、ディスパッチャーを使用してプログレスバー、ステータステキストブロックなどを更新します。
この後の問題は重要ではありません。
これらが興味を持っているファイル:
window.xaml.cs
public void repairButtonClick(object sender, RoutedEventArgs e)
{
repairButton.IsEnabled = false;
startButton.IsEnabled = false;
currentFile.Text = "Hashing files...";
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (object s, DoWorkEventArgs es) =>
{
scanner.search();
};
bw.RunWorkerCompleted += (object s, RunWorkerCompletedEventArgs ev) =>
{
toUpdateFiles = scanner.getToUpdateFiles();
if (toUpdateFiles != null && toUpdateFiles.Count > 0)
{
_startDownload();
}
else
{
currentFile.Text = "";
System.Windows.MessageBox.Show(this, "Your client is OK!", "Patcher");
startButton.IsEnabled = true;
}
};
bw.RunWorkerAsync();
}
これはこの1つ上のクリックイベントハンドラ、何の問題ですが、それは_startDownloadメソッドを呼び出します。
window.xaml。
void _startDownload()
{
HTTPDownloader downloader = new HTTPDownloader(toUpdateFiles, client,"source/");
DownloadListener listener = new DownloadListener(this, downloader);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (object s, DoWorkEventArgs e) =>
{
downloader.startDownload();
};
bw.RunWorkerAsync();
}
HTTPDownloader
CS
WebClient
DownloadListener
のラッパーです
BackgroundWorker
が
HTTPDownloader.startDownload()
メソッドを実行し、すべての
WebClient
のダウンロードイベント(およびいくつかの習慣を)聞くリスナーである
HTTPDownloader.cs
public void startDownload()
{
if (Progress != null) client.DownloadProgressChanged += Progress;
if (Completed != null) client.DownloadFileCompleted += Completed;
if (client.BaseAddress.Length == 0)
{
throw new Exception("BaseAddress missing in the WebClient Object");
}
for (int i = 0; i < files.Count; i++)
{
PatchFile file = files[i];
setCurrentIndex(i + 1);
OnNewFile(file);
setCurrentFile(file);
string path = Path.Combine(file.getBasePath(), file.getName());
string downloadPath = basePath + path;
if (file.basePath != String.Empty) Directory.CreateDirectory(Path.GetDirectoryName(path));
client.DownloadFileAsync(new Uri(new Uri(client.BaseAddress), downloadPath), path);
while (client.IsBusy)
{
}
OnAfterNewFile(file);
}
OnAllFileDownloaded();
}
ここでは、これが最も重要な方法です。
すべてのファイルをダウンロードし、いくつかのイベントを発生させます。
(offtopic質問:?while(client.isBusy)
はダウンロードがもう一方を開始するために終了するまで待つための良い方法です(I/O WebClientの例外を上げないために))
私は、私を助けてください傾いている。私と他のコンピュータで同じ実行可能ファイルが別の方法で実行されるのは当然のことです。
多分スレッドはさまざまな方法で管理されていますが、わかりませんが、私はアプリケーションプログラミングにはまったく新しいです(私のwindow.xaml.csにいくつかのビジネスロジックがあり、 ui(DownloadListener)、MVVCパターンを見たときに遅かった)。
おかげ
で問題を抱えていたホスティングだった '(client.isBusyは)'悪いながら。 CPUコアの1つをビジーにします。 'DownloadFile'を使用してください。あなたは既に 'BackgroundWorker'でUI以外のスレッドにいます。 try/catchを使用して例外を捕捉してログに記録する –