web-dev-qa-db-ja.com

.NET WebClientオブジェクトのタイムアウトを変更する方法

クライアントのデータをローカルマシンに(プログラムで)ダウンロードしようとしていますが、Webサーバーが非常に遅いため、WebClientオブジェクトでタイムアウトが発生しています。

ここに私のコードがあります:

WebClient webClient = new WebClient();

webClient.Encoding = Encoding.UTF8;
webClient.DownloadFile(downloadUrl, downloadFile);

このオブジェクトに無限のタイムアウトを設定する方法はありますか?または、そうでない場合、誰かがこれを行う別の方法の例で私を助けることができますか?

ブラウザでURLは正常に機能します-表示するのに約3分かかります。

210
Ryall

次の例のように、タイムアウトを延長できます。元のWebClientクラスを継承し、webrequestゲッターをオーバーライドして独自のタイムアウトを設定します。

私の場合、MyWebClientはプライベートクラスでした。

private class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
        WebRequest w = base.GetWebRequest(uri);
        w.Timeout = 20 * 60 * 1000;
        return w;
    }
}
356
kisp

最初の解決策は私にとってはうまくいきませんでしたが、私にとってはうまくいくコードがいくつかあります。

    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);
        }
    }
20
Davinci Jeremie

HttpWebRequestではなくWebClientを使用する必要がありますが、WebClientにタイムアウトを設定することはできません(HttpWebRequestを使用している場合でも)。代わりにHttpWebRequestを使用すると、タイムアウトを設定できます。

20
Fenton

ネットワークケーブルを抜いたときに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);
}
10
themullet

完全を期すために、ここに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
8
GlennG
'CORRECTED VERSION OF LAST FUNCTION IN VISUAL BASIC BY GLENNG

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  '<<< NOTICE: MyBase.GetWebRequest(address) DOES NOT WORK >>>
        End Function
7
Josh

Sohneeが言うように、 System.Net.HttpWebRequest を使用して、System.Net.WebClientを使用する代わりにTimeoutプロパティを設定します。

ただし、無限のタイムアウト値を設定することはできません(サポートされていないため、そうしようとするとArgumentOutOfRangeExceptionがスローされます)。

最初に HEAD HTTP リクエストを実行し、返されたContent-Lengthヘッダー値を調べてダウンロードしているファイルのバイト数を判断し、その後のGETリクエストまたは単にリクエストのタイムアウト値を設定することをお勧めします超過するとは思わない非常に長いタイムアウト値を指定します。

7
dariom

使用法:

using (var client = new TimeoutWebClient(TimeSpan.FromSeconds(10)))
{
    return await client.DownloadStringTaskAsync(url);
}

クラス:

using System;
using System.Net;

namespace Utilities
{
    public class TimeoutWebClient : WebClient
    {
        public TimeSpan Timeout { get; set; }

        public TimeoutWebClient(TimeSpan timeout)
        {
            Timeout = timeout;
        }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            var request = base.GetWebRequest(uri);
            if (request == null)
            {
                return null;
            }

            var timeoutInMilliseconds = (int) Timeout.TotalMilliseconds;

            request.Timeout = timeoutInMilliseconds;
            if (request is HttpWebRequest httpWebRequest)
            {
                httpWebRequest.ReadWriteTimeout = timeoutInMilliseconds;
            }

            return request;
        }
    }
}
2
Konstantin S.