Установить тайм-аут для webClient.DownloadFile ()

92

Я использую webClient.DownloadFile()для загрузки файла, могу ли я установить для этого тайм-аут, чтобы это не заняло много времени, если он не может получить доступ к файлу?

UnkwnTech
источник

Ответы:

42

Попробуй WebClient.DownloadFileAsync(). Вы можете позвонить CancelAsync()по таймеру с собственным таймаутом.

Абатищев
источник
2
Я не хочу использовать таймер или секундомер. Мне нужен встроенный хакерский или API-подход. Использование таймера / секундомера требует дополнительных потоков для просмотра, хотя эта функция, возможно, уже реализована, так зачем заново изобретать колесо
@Kilanny: тогда используйте решение из другого ответа. Или используйте HttpClient и установите свойство Timeout. Также обратите внимание, что это ответ от 2009 года.
Абатищев
8
в .Net 4.5+ вы также можете использовать, var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")а затемtaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho 03
258

Мой ответ идет отсюда

Вы можете создать производный класс, который будет устанавливать свойство тайм-аута базового WebRequestкласса:

using System;
using System.Net;

public class WebDownload : WebClient
{
    /// <summary>
    /// Time in milliseconds
    /// </summary>
    public int Timeout { get; set; }

    public WebDownload() : this(60000) { }

    public WebDownload(int timeout)
    {
        this.Timeout = timeout;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        if (request != null)
        {
            request.Timeout = this.Timeout;
        }
        return request;
    }
}

и вы можете использовать его так же, как базовый класс WebClient.

Бениамин
источник
3
На всякий случай, если кто-то еще наткнется на этот полезный код, мне пришлось установить тайм-аут перед вызовом base.GetWebRequest (адрес)
Дарттонг
Resharper жалуется на возможное нулевое значение для «результата» и предлагает нулевую проверку перед установкой значения Timeout для WebRequest. Глядя на декомпилированный код, это кажется невозможным, если вы не предоставите пользовательский WebRequestModules в своем web.config, но для такого ответа с одобрением я бы добавил его на всякий случай.
Кевин Куломб
Я получаю сообщение об ошибке в этой строке request.Timeout. Сообщение об ошибке 'System.Net.WebRequest' does not contain a definition for 'Timeout' and no extension method 'Timeout' accepting a first argument of type 'System.Net.WebRequest' could be found (are you missing a using directive or an assembly reference?) , что мне не хватает?
Эрик
1
@Eric: Я добавил usingдирективы, которые используются в этом фрагменте кода.
Beniamin
1
@titol: используйте HttpClient, а не WebClient.
Абатищев
3

Предполагая, что вы хотите сделать это синхронно, используя метод WebClient.OpenRead (...) и установив тайм-аут в потоке, который он возвращает, даст вам желаемый результат:

using (var webClient = new WebClient())
using (var stream = webClient.OpenRead(streamingUri))
{
     if (stream != null)
     {
          stream.ReadTimeout = Timeout.Infinite;
          using (var reader = new StreamReader(stream, Encoding.UTF8, false))
          {
               string line;
               while ((line = reader.ReadLine()) != null)
               {
                    if (line != String.Empty)
                    {
                        Console.WriteLine("Count {0}", count++);
                    }
                    Console.WriteLine(line);
               }
          }
     }
}

Получение из WebClient и переопределение GetWebRequest (...) для установки тайм-аута, предложенного @Beniamin, для меня не сработало, но это сработало.

Джеффриморрис
источник
@jeffymorris у меня не работал. Я все еще получаю WebException, говорящий «запрос был прерван - время ожидания операции истекло», даже если я stream.ReadTimeout
укажу
@jeffymoris, с другой стороны, решение с подклассом webclient тоже не сработало, так что это, вероятно, проблема на стороне сервера
chester89