3

C# で WebClient を使用してファイルをダウンロードしています。client.DownloadFileAsnyc() を使用しています。以前はこれで問題なく動作していましたが、例外はすべてキャッチされ、完了ハンドラー (AsyncCompletedEventArgs.Error) で返されていました。

しかし、ダウンロード中に宛先の場所のスペースが不足すると、IOExcption がスローされ、アプリがクラッシュすることがわかりました。これが完了ハンドラで捕捉されて返されない理由を誰かが知っていますか?
注: DownloadFileAsync 行を try catch に入れることも試みました。まだ行かない

コードは次のとおりです。

_client = new WebClient();
_client.DownloadProgressChanged += ProgressChanged;
_client.DownloadFileCompleted += DownloadComplete;
_client.DownloadFileAsync(new Uri(url), Destination);

private void DownloadComplete(object sender, AsyncCompletedEventArgs args)
{
}

これは .NET 3.5 でコンパイルされています。

4

1 に答える 1

0

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 秒以上かかる大きなファイルに使用している場合は、システム スレッドプールを少し悪用していることに注意してください。大きなファイルをダウンロードする場合、または多くのファイルを同時にダウンロードする場合は、絶対にこの方法を実行しないでください。

于 2013-06-12T14:47:05.013 に答える