2013-06-12 3 views
3

Я использую WebClient в C# для загрузки файла. Я использую client.DownloadFileAsnyc(). Раньше это работало нормально, любые исключения были бы пойманы и возвращены в обработчике завершения (AsyncCompletedEventArgs.Error)DownloadFileAsync бросает необработанные исключения?

Но теперь я обнаружил, что если во время загрузки у меня заканчивается место в месте назначения, IOExcption бросается и приводит к сбою приложения. Кто-нибудь знает, почему это не будет поймано и возвращено в обработчике завершения?
Примечание. Я также попытался помещать строку DownloadFileAsync в попытку 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

Где исключение попадает? – Romoku

+0

В стеке вызовов говорится: «[Внешний код]», никаких других деталей я не вижу: \ –

ответ

0

MSDN docs for System.ComponentModel указывает, что ваш обработчик DownloadFileCompleted должен действительно получить исключение, но, по-видимому, этого здесь не происходит. Вы можете попробовать подключить некоторые другие * Завершенные события на WebClient, чтобы узнать, отправляется ли он туда.

В любом случае вы не поймаете исключение, потому что это не происходит в потоке, который выполняет блок try/catch.

Когда вы используете функции async api (что обычно означает любое имя функции, которое заканчивается на «Async» или «Begin»), фактическая операция выполняется в threadpool, а не в потоке, в котором вы запустили операцию. Окружение операции в try/catch не будет ловить сбои в фоновом потоке.

Чтобы правильно убрать все исключения в приложении, вы можете установить global exception handler, который будет вызываться всякий раз, когда генерируется исключение, которое не попадает в другое место в вашей программе.

Одним из простых способов такого поведения было бы использование синхронной функции 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); 

Пожалуйста, обратите внимание, что этот пример немного злоупотребления системы ThreadPool, особенно если вы используете его для больших файлов, где закачка будет более чем на секунду или около того. Если вы загружаете большие файлы или загружаете много файлов одновременно, вы определенно не должны этого делать.

Смежные вопросы