Dav*_*cía 0 c# android webrequest android-asynctask
之前我问过这个问题,但是我打算用一个解决方案来完成这个问题并提出另一个问题.
我正在使用这个类来创建异步WebRequest:
class HttpSocket
{
public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用以下代码测试该类:
class Program
{
static void Main(string[] args)
{
// Making a request to a nonexistent domain.
HttpSocket.MakeRequest(new Uri("http://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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
一旦执行,立即到达回调,显示"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<RequestCallbackState> ResponseCallback { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这种方法有效.我建议将其切换为显式处理异常(包括您的超时,但也包括坏域名等)略有不同.在这种情况下,我将其拆分为一个单独的延续.
另外,为了使这个非常明确,我缩短了超时时间,放入了一个"真实"但速度较慢的域,并添加了一个明确的超时状态,你可以看到:
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<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(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<RequestCallbackState> ResponseCallback { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Making a request to a nonexistent domain.
HttpSocket.MakeRequest(new Uri("http://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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将运行,并适当显示超时.