System.ComponentModelのMSDN ドキュメントは、 DownloadFileCompleted ハンドラーが実際に例外を受け取る必要があることを示していますが、明らかにここでは発生していません。WebClient で他の *Completed イベントのいくつかをフックして、そこに送信されているかどうかを確認してみてください。
いずれにせよ、try / catch ブロックを実行するスレッドで例外が発生していないため、例外をキャッチしていません。
async api 関数 (通常、「Async」または「Begin」で終わる関数名を意味します) を使用すると、実際の操作は、操作を開始したスレッドではなく、スレッドプールで行われます。操作を try/catch で囲んでも、バックグラウンド スレッドでの失敗はキャッチされません。
アプリケーション内のすべての例外を適切にキャッチするために、プログラム内のどこかでキャッチされない例外がスローされるたびに呼び出されるグローバル例外ハンドラーをインストールできます。
この動作を回避する簡単な方法の 1 つは、同期 client.DownloadFile() 関数を使用し、その関数をバックグラウンド スレッドから呼び出して、プログラムのメイン スレッドをブロックしないようにすることです。これを示す簡単な例を次に示します。
// create a thread function to download a file synchronously
function DoDownload(object state){
List<String> st = (List<String>)(state);
String uri = st[0];
String fname = st[1];
try {
client.DownloadFile(uri, fname);
} catch {
// you'll catch the exception here because the
// try/catch is on the same thread that is doing the downloading
}
}
// somewhere else, when you want to actually start the download:
String uri = "http://example.com/the_file.txt";
string theFileName = "destination.txt";
List<String> st = new List<String>{ theUri, theFileName };
ThreadPool.QueueUserWorkItem(DoDownload, st);
この例は、特にダウンロードに 1 秒以上かかる大きなファイルに使用している場合は、システム スレッドプールを少し悪用していることに注意してください。大きなファイルをダウンロードする場合、または多くのファイルを同時にダウンロードする場合は、絶対にこの方法を実行しないでください。