如何为HttpWebRequest定义更积极的超时?

在可移植类库中,我有以下方法将数据发布到特定的Url。 该方法效果很好。 但是我想指定一个更积极的超时(默认为100秒)。

考虑到来自可移植类库的HttpWebRequest类没有Timeout属性,如何在超过几秒的时间内确保调用被放弃?

public async Task PostAsync(Uri uri, string data) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; using (Stream requestStream = await request.GetRequestStreamAsync()) { byte[] postBytes = Encoding.UTF8.GetBytes(data); requestStream.Write(postBytes, 0, postBytes.Length); } HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); return new HttpResponse(response.StatusCode, await new StreamReader(response.GetResponseStream()).ReadToEndAsync()); } 

下面的代码将返回一个HttpWebResponse,如果超时则返回null。

 HttpWebResponse response = await TaskWithTimeout(request.GetResponseAsync(), 100); if(response != null) { .... } 

 Task TaskWithTimeout(Task task, int duration) { return Task.Factory.StartNew(() => { bool b = task.Wait(duration); if (b) return (HttpWebResponse)task.Result; return null; }); } 

– 编辑 –

创建扩展方法会更好

 public static class SOExtensions { public static Task WithTimeout(this Task task, int duration) { return Task.Factory.StartNew(() => { bool b = task.Wait(duration); if (b) return task.Result; return default(T); }); } } 

用法是:

 var response = (HttpWebResponse)await request.GetResponseAsync().WithTimeout(1000); 

–EDIT 2–

另一种方式

 public async static Task WithTimeout(this Task task, int duration) { var retTask = await Task.WhenAny(task, Task.Delay(duration)) .ConfigureAwait(false); if (retTask is Task) return task.Result; return default(T); } 
 // Abort the request if the timer fires. private static void TimeoutCallback(object state, bool timedOut) { if (timedOut) { HttpWebRequest request = state as HttpWebRequest; if (request != null) { request.Abort(); } } } 

是的,客户端应用程序有责任实现自己的超时机制。 您可以从上面设置超时的代码执行此操作,并使用ThreadPool.RegisterWaitForSingleObject方法。 有关完整详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.abort.aspx 。 从本质上讲,它会从GetResponse,BeginGetResponse,EndGetResponse,GetRequestStream,BeginGetRequestStream或EndGetRequestStream中止。