来自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(); }); }
这适用于我(如果我设置超时持续时间非常短,并点击此,我总是适当地超时)。