我在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下编译的。
答案 0 :(得分:0)
MSDN docs for System.ComponentModel表示你的DownloadFileCompleted处理程序确实应该收到异常,但显然这里没有发生。您可以尝试在WebClient上挂钩其他一些*已完成的事件,看看是否已将其发送到那里。
在任何情况下,您都没有捕获异常,因为它不会在执行try / catch块的线程上发生。
当您使用async api函数(通常表示以“Async”或“Begin”结尾的任何函数名称)时,实际操作发生在线程池中,而不是在您启动操作的线程上。在try / catch中包围操作不会捕获后台线程上的失败。
要正确捕获应用程序中的所有异常,您可以安装global exception handler,只要抛出未在程序中其他位置捕获的异常,就会调用该{{3}}。
解决此问题的一种简单方法是使用同步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);
请注意,此示例有点滥用系统线程池,特别是如果您将其用于大型文件,其中下载将花费超过一秒钟左右。如果你正在下载更大的文件,或者同时下载许多文件,你绝对不应该这样做。