在异步请求中使用超时回调
之前我问过这个问题,但我打算用提出的解决方案来完成这个问题并提出另一个问题。
我正在使用这个类来创建异步WebRequest :
class HttpSocket { public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; Task asyncTask = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true); asyncTask.ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }); } private static void TimeoutCallback(object state, bool timedOut) { Console.WriteLine("Timeout: " + timedOut); if (timedOut) { Console.WriteLine("Timeout"); WebRequest request = (WebRequest)state; if (state != null) { request.Abort(); } } } }
我正在使用以下代码测试该类:
class Program { static void Main(string[] args) { // Making a request to a nonexistent domain. HttpSocket.MakeRequest(new Uri("https://www.google.comhklhlñ"), callbackState => { if (callbackState.Exception != null) throw callbackState.Exception; Console.WriteLine(GetResponseText(callbackState.ResponseStream)); }); Thread.Sleep(100000); } public static string GetResponseText(Stream responseStream) { using (var reader = new StreamReader(responseStream)) { return reader.ReadToEnd(); } } }
一旦执行,立即到达回调,显示“Timeout:false”并且没有更多的抛出,因此超时不起作用。
这是原始线程中提出的解决方案,但正如您所看到的,代码适用于他。
我做错了什么?
编辑:代码使用的其他类:
class RequestCallbackState { public Stream ResponseStream { get; private set; } public Exception Exception { get; private set; } public RequestCallbackState(Stream responseStream) { ResponseStream = responseStream; } public RequestCallbackState(Exception exception) { Exception = exception; } } class RequestState { public byte[] RequestBytes { get; set; } public WebRequest Request { get; set; } public Action ResponseCallback { get; set; } }
这种方法有效。 我建议将其切换为显式处理exception(包括您的超时,但也包括坏域名等)略有不同。 在这种情况下,我将其拆分为一个单独的延续。
另外,为了使这一点非常明确,我缩短了超时时间,放入了一个“真实”但速度较慢的域,并添加了一个明确的超时状态,你可以看到:
using System; using System.IO; using System.Net; using System.Threading; using System.Threading.Tasks; class HttpSocket { private const int TimeoutLength = 100; public static void MakeRequest(Uri uri, Action responseCallback) { WebRequest request = WebRequest.Create(uri); request.Proxy = null; Task asyncTask = Task.Factory.FromAsync (request.BeginGetResponse, request.EndGetResponse, null); ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, TimeoutLength, true); asyncTask.ContinueWith(task => { WebResponse response = task.Result; Stream responseStream = response.GetResponseStream(); responseCallback(new RequestCallbackState(response.GetResponseStream())); responseStream.Close(); response.Close(); }, TaskContinuationOptions.NotOnFaulted); // Handle errors asyncTask.ContinueWith(task => { var exception = task.Exception; var webException = exception.InnerException; // Track whether you cancelled or not... up to you... responseCallback(new RequestCallbackState(exception.InnerException, webException.Message.Contains("The request was canceled."))); }, TaskContinuationOptions.OnlyOnFaulted); } private static void TimeoutCallback(object state, bool timedOut) { Console.WriteLine("Timeout: " + timedOut); if (timedOut) { Console.WriteLine("Timeout"); WebRequest request = (WebRequest)state; if (state != null) { request.Abort(); } } } } class RequestCallbackState { public Stream ResponseStream { get; private set; } public Exception Exception { get; private set; } public bool RequestTimedOut { get; private set; } public RequestCallbackState(Stream responseStream) { ResponseStream = responseStream; } public RequestCallbackState(Exception exception, bool timedOut = false) { Exception = exception; RequestTimedOut = timedOut; } } class RequestState { public byte[] RequestBytes { get; set; } public WebRequest Request { get; set; } public Action ResponseCallback { get; set; } } class Program { static void Main(string[] args) { // Making a request to a nonexistent domain. HttpSocket.MakeRequest(new Uri("https://www.tanzaniatouristboard.com/"), callbackState => { if (callbackState.RequestTimedOut) { Console.WriteLine("Timed out!"); } else if (callbackState.Exception != null) throw callbackState.Exception; else Console.WriteLine(GetResponseText(callbackState.ResponseStream)); }); Thread.Sleep(100000); } public static string GetResponseText(Stream responseStream) { using (var reader = new StreamReader(responseStream)) { return reader.ReadToEnd(); } } }
这将运行,并适当显示超时。
使用2个不同的类:
class RequestCallbackException : Exception { public RequestCallbackException(Stream responseStream, Exception exception) : base(exception) { } }
和
class RequestCallbackStream { public Stream ResponseStream { get; private set; } public RequestCallbackState(Stream responseStream) { ResponseStream = responseStream; } }
您会注意到有时GetResponseStream()会返回null,这会立即引发exception
上述就是C#学习教程:在异步请求中使用超时回调分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
asyncTask.ContinueWith() --> GetResponseText(callbackState.ResponseStream)--> using (var reader = new StreamReader(responseStream)) // responseStream is null { }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1012112.html