构建HttpWebRequest超时问题的解决方法

时间:2011-05-27 15:26:22

标签: wcf rest asynchronous

我正在使用HTTP Web Request类来调用RESTful Web服务。我需要传递数据并接收数据,这一切似乎都很有效。今天我试图配置类的超时,因为运行服务的服务器很可能处于脱机状态,我不想浪费时间等待。我配置了它,但似乎没有任何区别。在失败之前,呼叫仍然等待超过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 :(得分:0)

调用回调函数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)这样的平台,在这些平台上禁止同步调用(即使那些打扮成异步的调用)。