Я пытаюсь загрузить данные клиента на свой локальный компьютер (программно), и их веб-сервер очень медленный, что вызывает таймаут в моем WebClient объекте.
Вот мой код:
WebClient webClient = new WebClient();
webClient.Encoding = Encoding.UTF8;
webClient.DownloadFile(downloadUrl, downloadFile);
Есть ли способ установить бесконечный тайм-аут на этом объекте? Или, если нет, кто-нибудь может помочь мне с примером по альтернативному способу сделать это?
URL-адрес отлично работает в браузере - для отображения требуется всего около 3 минут.
Как говорит Sohnee, используя System.Net.HttpWebRequest и устанавливая свойство Timeout вместо использования System.Net.WebClient.
Вы не можете установить бесконечное значение таймаута (оно не поддерживается и не пытается сделать так что выкинет ArgumentOutOfRangeException).
Я бы рекомендовал сначала выполнить запрос System.Net.HttpWebRequest и изучить значение заголовка Content-Length, возвращаемое для определения количества байтов в файл, который вы загружаете, а затем устанавливаете значение таймаута соответственно для последующего запроса GET или просто указываете очень длинное значение таймаута, которое вы никогда не ожидаете превышать.
Первое решение не сработало для меня, но вот какой-то код, который работал для меня.
private class WebClient : System.Net.WebClient
{
public int Timeout { get; set; }
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest lWebRequest = base.GetWebRequest(uri);
lWebRequest.Timeout = Timeout;
((HttpWebRequest)lWebRequest).ReadWriteTimeout = Timeout;
return lWebRequest;
}
}
private string GetRequest(string aURL)
{
using (var lWebClient = new WebClient())
{
lWebClient.Timeout = 600 * 60 * 1000;
return lWebClient.DownloadString(aURL);
}
}
Для полноты, вот решение kisp портировано на VB (не может добавить код в комментарий)
Namespace Utils
''' <summary>
''' Subclass of WebClient to provide access to the timeout property
''' </summary>
Public Class WebClient
Inherits System.Net.WebClient
Private _TimeoutMS As Integer = 0
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal TimeoutMS As Integer)
MyBase.New()
_TimeoutMS = TimeoutMS
End Sub
''' <summary>
''' Set the web call timeout in Milliseconds
''' </summary>
''' <value></value>
Public WriteOnly Property setTimeout() As Integer
Set(ByVal value As Integer)
_TimeoutMS = value
End Set
End Property
Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest
Dim w As System.Net.WebRequest = MyBase.GetWebRequest(address)
If _TimeoutMS <> 0 Then
w.Timeout = _TimeoutMS
End If
Return w
End Function
End Class
End Namespace
Не удалось заставить код w.Timeout работать, когда вытащил сетевой кабель, он просто не синхронизировался, перешел на использование HttpWebRequest и выполнил эту работу сейчас.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downloadUrl);
request.Timeout = 10000;
request.ReadWriteTimeout = 10000;
var wresp = (HttpWebResponse)request.GetResponse();
using (Stream file = File.OpenWrite(downloadFile))
{
wresp.GetResponseStream().CopyTo(file);
}
Вам нужно использовать HttpWebRequest, а не WebClient, поскольку вы не можете установить тайм-аут на WebClient без его расширения (хотя он использует HttpWebRequest). Использование HttpWebRequest вместо этого позволит вам установить тайм-аут.