简体   繁体   English

DownloadFileAsync抛出未处理的异常?

[英]DownloadFileAsync throwing unhandled exceptions?

I'm using a WebClient in C# to download a file. 我在C#中使用WebClient来下载文件。 I'm using client.DownloadFileAsnyc(). 我正在使用client.DownloadFileAsnyc()。 In the past this worked fine, any exceptions would be caught and returned in the completion handler (AsyncCompletedEventArgs.Error) 在过去,这工作正常,任何异常都将被捕获并在完成处理程序中返回(AsyncCompletedEventArgs.Error)

But now I'm finding that if I run out of space in the destination location during the download, the IOExcption is getting thrown and causing the app to crash. 但是现在我发现如果我在下载过程中目标位置的空间不足,IOExcption就会被抛出并导致应用程序崩溃。 Does anyone know why this wouldn't be caught and returned in the completion handler? 有谁知道为什么这不会被捕获并在完成处理程序中返回?
Note: I've also tried putting the DownloadFileAsync line in a try catch. 注意:我也尝试将DownloadFileAsync行放在try catch中。 Still no go 仍然没有去

Here's the code: 这是代码:

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

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

This is being compiled under .NET 3.5. 这是在.NET 3.5下编译的。

The MSDN docs for System.ComponentModel indicate that your DownloadFileCompleted handler should indeed receive the exception, but apparently that isn't happening here. System.ComponentModelMSDN文档表明您的DownloadFileCompleted处理程序确实应该收到异常,但显然这不会发生。 You might try hooking some of the other *Completed events on WebClient to see if it is getting sent there. 您可以尝试在WebClient上挂钩其他*已完成事件以查看是否已将其发送到那里。

In any case, you aren't catching the exception because it isn't happening on the thread that executes the try / catch block. 在任何情况下,您都没有捕获异常,因为它不会在执行try / catch块的线程上发生。

When you use the async api functions (which generally means any function name that ends with "Async" or "Begin"), the actual operation happens in the threadpool, not on the thread where you launched the operation. 当您使用async api函数(通常表示以“Async”或“Begin”结尾的任何函数名称)时,实际操作发生在线程池中,而不是在您启动操作的线程上。 Surrounding the operation in a try/catch will not catch failures on the background threads. 在try / catch中围绕操作不会捕获后台线程上的故障。

To properly catch all exceptions in your application, you can install a global exception handler that will be called whenever an exception is thrown that isn't caught somewhere else in your program. 要正确捕获应用程序中的所有异常,可以安装一个全局异常处理程序 ,只要抛出未在程序中的其他位置捕获的异常,就会调用该处理程序。

One easy way around this behavior would be to use the synchronous client.DownloadFile() function, and then call that function from a background thread so you don't block the main thread of your program. 解决此问题的一种简单方法是使用同步client.DownloadFile()函数,然后从后台线程调用该函数,这样就不会阻止程序的主线程。 Here is a quick-and-dirty example that demonstrates it: 这是一个快速而肮脏的例子,它演示了它:

// 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);

Please note, this example is a bit of an abuse of the system threadpool, especially if you are using it for large files where the download will take more than a second or so. 请注意,此示例有点滥用系统线程池,特别是如果您将其用于下载大约需要一秒钟左右的大型文件。 If you are downloading larger files, or are downloading many files simultaneously, you definitely should not do it this way. 如果您正在下载较大的文件,或者同时下载许多文件,那么您绝对不应该这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM