Harisri Ответов: 3

Httpwebresponse выдает ошибку "время ожидания операции истекло"


У меня есть такой код:

public class WebDataDownloader
{
    public string GetJSONFromURL(string url)
    {
         string file = string.empty;
         //*********get the json file using httpRequest ***********

         try
         {
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest.Method = WebRequestMethods.Http.Get;
            httpWebRequest.Accept = "application/json; charset=utf-8";
            //httpWebRequest.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36";
            //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

            using (var response = (HttpWebResponse)httpWebRequest.GetResponse())
            {
                using (var sr = new StreamReader(response.GetResponseStream()))
                {
                    file = sr.ReadToEnd();
                }
            }
        }
        catch(Exception exp)
        {
            Debug.WriteLine(exp.Message);
        }

        return file;
    }
}


Теперь я вызываю этот метод несколько раз в своем основном потоке, чтобы получить JSON и разобрать его. Что-то вроде приведенного ниже:

public class MyClass
{
    WebDataDownloader myWebClient = new WebDataDownloader();
    string Json1 = myWebClient.GetJSONFromURL(@"https://www.nseindia.com/api/market-data-pre-open?key=ALL");

    //Do some action on this data

    string Json2 = myWebClient.GetJSONFromURL(@"https://www.nseindia.com/api/equity-stock?index=fu_nifty50");

    //Do some action on this data

    string Json3 = myWebClient.GetJSONFromURL(@"https://www.nseindia.com/api/liveEquity-derivatives?index=nifty_bank_fut");

    //Do some action on this data
}


Но проблема в том, что первый вызов для (Json1) использует

response = (HttpWebResponse)httpWebRequest.GetResponse()


работает нормально, но 2-й и 3-й вызовы не работают в одном экземпляре.

Что я уже пробовал:

Я просмотрел много постов на разных форумах, но все эти посты довольно старые, и я думаю, что испробовал все уловки. Попробовал то же самое и с WebClient, но безуспешно. Код, который я упомянул, - это код, который прекрасно работал до 7-8 месяцев назад с Раскомментированным свойством агента пользователя. Именно в последнее время он начал терпеть неудачу для нескольких URL-адресов.

Может ли кто-нибудь помочь мне с этим?..

Заранее спасибо.

3 Ответов

Рейтинг:
2

Harisri

Вы имеете в виду, что HTTPWebRequest также помещается в оператор using?
Но мы не можем этого сделать, потому что он не реализует IDisposable.


Рейтинг:
1

Garth J Lancaster

Интересно, это потому, что вы (повторно)используете (плохой каламбур) старый экземпляр HttpWebRequest - что произойдет, если вы сделаете это (возможно, потребуется массаж) :-

using HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
{
    httpWebRequest.Method = WebRequestMethods.Http.Get;
    httpWebRequest.Accept = "application/json; charset=utf-8";

    using (var response = (HttpWebResponse)httpWebRequest.GetResponse())
    {
        using (var sr = new StreamReader(response.GetResponseStream()))
        {
            file = sr.ReadToEnd();
        }
    }
}


У меня было искушение свернуть "использование" в как можно меньшее количество блоков, но это, вероятно, более понятно из вашего POV


Рейтинг:
0

Pete O'Hanlon

Честно говоря, если бы у вас была такая возможность, я бы вообще отказался от использования HttpWebResponse и пошел с более новым подходом .NET к использованию HttpClient. Ваш код может выглядеть примерно так:

public class HttpRequestManager
{
  private readonly IHttpClientFactory httpClientFactory;
  public HttpRequestManager(IHttpClientFactory httpClientFactory)
  {
    this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
  }

  public async Task<string> GetJSONFromUrlAsync(string url, CancellationToken token = CancellationToken.None)
  {
    using (var client = httpClientFactory.CreateClient());
    using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url));
    using (var response = await client.SendAsync(request, token));
    response.EnsureSuccessStatusCode();
    string rawData = await response.Content.ReadAsStringAsync();
    return rawData;
  }
}
Обратите внимание, что в этом могут быть некоторые незначительные синтаксические ошибки, так как я только что постучал в блокнот, чтобы продемонстрировать технику. Заставьте это работать, и у вас нет блокирующей способности загрузки.


Harisri

Привет, я мог бы немного усовершенствовать и исправить ваш код вот так:

Открытый класс HttpRequestManager
{
частная чтения IHttpClientFactory httpClientFactory;

public HttpRequestManager(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
}

public async Task<string> GetJSONFromUrlAsync(string url, CancellationToken cancellationToken = default(CancellationToken))
{
string rawData = строка.Пустой;

использование (var client = httpClientFactory.CreateClient())
{
используя (объектами httprequestmessage запрос = новый объектами httprequestmessage(HttpMethod.Get, url))
{
использование (var response = await client.SendAsync(запрос, cancellationToken))
{
ответ.EnsureSuccessStatusCode();
rawData = ожидание ответа.Содержание.ReadAsStringAsync();
}
}
}
вернуться сырых данных;
}
}

Но когда мне приходится вызывать метод для возврата данных, я не могу понять, как создать экземпляр указанного вами класса.

HttpRequestManager myHTTPManager = новый HttpRequestManager((IHttpClientFactory)DefaultHttpClientFactory);
Задача<string> jsonData = myHTTPManager.GetJSONFromUrlAsync(myUrl);

Я имею в виду, как передать аргументы конструктору HttpRequestManager. Пожалуйста, проводите меня...

Pete O'Hanlon

Извините, что у меня не было возможности ответить раньше; IHttpClientFactory обычно вводится в ваш код, если вы используете .NET Core и используете DefaultHttpClientFactory. Если вы не используете инъекцию зависимостей, вы можете удалить конструктор и заменить первый оператор using на (using HttpClient client = new HttpClient())

Кстати, формат оператора using, который вы видели в моем примере, был новым способом добавления блоков using (введенным в C# 8). Вы можете найти подробную информацию здесь: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations