Csharp/C#教程:在异步请求中使用超时回调分享


在异步请求中使用超时回调

之前我问过这个问题,但我打算用提出的解决方案来完成这个问题并提出另一个问题。

我正在使用这个类来创建异步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

(0)
上一篇 2021年12月30日
下一篇 2021年12月30日

精彩推荐