来自exception超时的任务

我有这段代码来发出异步HTTP请求:

public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }); } 

它有效,但我需要设置一个请求超时。 我试图使用request.Timeout但似乎什么也没做。 有没有办法在此代码中设置任务超时?

编辑添加新的超时回调。 新代码:

  public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; IAsyncResult t = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }); ThreadPool.RegisterWaitForSingleObject(t.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true); } private static void TimeoutCallback(object state, bool timedOut) { if (timedOut) { Console.WriteLine("Timeout"); WebRequest request = (WebRequest)state; if (state != null) { request.Abort(); } } } 

测试用:

 HttpSocket.MakeRequest(new Uri("http://www.google.comhklhlñ"), callbackState => { if (callbackState.Exception != null) throw callbackState.Exception; Console.WriteLine(GetResponseText(callbackState.ResponseStream)); }); Thread.Sleep(10000); 

从Timeout文档 :

Timeout属性对使用BeginGetResponse或BeginGetRequestStream方法进行的异步请求没有影响。

这是因为框架会强制您自己处理超时。 您应该能够在此处使用示例代码 ,除了将从FromAsync调用返回的Task传递给ThreadPool.RegisterWaitForSingleObject方法。


编辑:

您需要将注册放在原始任务上,而不是继续:

 public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; const int TimeoutPeriod = 1000; Task t = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); ThreadPool.RegisterWaitForSingleObject((t as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, TimeoutPeriod, true); t.ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(response.GetResponseStream()); responseStream.Close(); response.Close(); }); } 

这适用于我(如果我设置超时持续时间非常短,并点击此,我总是适当地超时)。