Создание обходного пути для проблемы тайм-аута HttpWebRequest - PullRequest
0 голосов
/ 27 мая 2011

Я использую класс веб-запроса HTTP для вызова веб-службы RESTful.Мне нужно передать данные и получить данные, и все это, кажется, работает очень хорошо.Сегодня я попытался настроить время ожидания класса, потому что существует высокая вероятность того, что сервер, на котором запущена служба, находится в автономном режиме, и я не хочу тратить время на ожидание.Я все это настроил, но, похоже, ничего не изменилось.Звонок все еще ждал более 10 секунд, прежде чем потерпел неудачу.

При просмотре я обнаружил, что тайм-аут касается только обработки вызова и что предварительный поиск DNS не включен.Поскольку это было бы проблемой, было бы понятно, почему тайм-аут не работает так, как я ожидал.

Для дальнейшего чтения предлагается использовать класс HttpWebRequest в асинхронном стиле.Я посмотрел на код, чтобы сделать это, но не понимаю, как получить обратный вызов в моем коде, который является эффективно синхронным.

У меня следующий код:

HttpWebRequest _serviceRequest = (HttpWebRequest)WebRequest.Create(new Uri("http://mywebservice.com"));
_serviceRequest.Timeout = 3000;

HttpWebResponse response = (HttpWebResponse)_serviceRequest.GetResponse();
XmlReader reader = XmlReader.Create(response.GetResponseStream(), set);

Код, который я должен вызвать асинхронно, заканчивается следующей строкой, но я не уверен, что мне делатьчтобы получить объект ответа.

IAsyncResult result = (IAsyncResult)req.BeginGetResponse(new AsyncCallback(RespCallback), reqState);

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

Любые помощники оценили ...

1 Ответ

0 голосов
/ 27 мая 2011

Ответ будет доступен при вызове функции обратного вызова RespCallback.Я не знаю, что имеет reqState, но я предполагаю, что он содержит ссылку на оригинальный объект HttpWebRequest.Если это так, то это будет простая реализация метода RespCallback:

void RespCallback(IAsyncResult asyncResult)
{
   ReqState reqState = (ReqState)asyncResult.AsyncState;
   HttpWebResponse resp = (HttpWebResponse)reqState.Request.EndGetResponse(asyncResult);
   // do what you need with the response.
}

Обновление: больше информации, как указано в комментарии

Если вы хотитеответ в том же методе, где вы выполняли вызов Begin, вы можете иметь событие, которое будет установлено при получении обратного вызова, и вы можете ждать этого события после вызова Begin, как в примере ниже

class ReqState {
    public HttpWebRequest Request { get; set; }
    public HttpWebResponse Response { get; set; }
    public AutoResetEvent Evt { get; set; }
}

void RespCallback(IAsyncResult asyncResult) {
    ReqState reqState = (ReqState)asyncResult.AsyncState;
    reqState.Response = (HttpWebResponse)reqState.Request.EndGetResponse(asyncResult);
    reqState.Evt.Set();
}

void CallMethod() {
    HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(...);
    // set properties on req
    ReqState state = new ReqState();
    state.Request = req;
    state.Evt = new ManualResetEvent(false);
    req.BeginGetResponse(RespCallback, state);
    state.Evt.WaitOne(TimeSpan.FromSeconds(30)); // wait for 30 seconds
    // access response via state.Response
}

Теперь обратите внимание, что по сути вы делаете синхронный вызов асинхронным способом.Это дает вам больше контроля над временем ожидания, но с ценой сложности кода.Другое дело, что это не будет работать на платформах, таких как Silverlight (и Windows Phone, IIRC), где синхронные вызовы (даже если они одеты как асинхронные) запрещены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...