我问过这个问题,但我会完成与提出的解决方案的问题,并做出另一个问题。
我使用这个类进行异步的WebRequest < /一>:
类HttpSocket
{
公共静态无效MakeRequest(URI URI,动作&LT; RequestCallbackState&GT; responseCallback)
{
WebRequest的请求= WebRequest.Create(URI);
request.Proxy = NULL;
任务&LT; WebResponse的&GT; AsyncTask的= Task.Factory.FromAsync&LT; WebResponse的&GT;(request.BeginGetResponse,request.EndGetResponse,NULL);
ThreadPool.RegisterWaitForSingleObject((AsyncTask的为IAsyncResult的).AsyncWaitHandle,新WaitOrTimerCallback(TimeoutCallback)的要求,1000年,真正的);
asyncTask.ContinueWith(任务=&GT;
{
WebResponse的响应= task.Result;
流responseStream = response.GetResponseStream();
responseCallback(新RequestCallbackState(response.GetResponseStream()));
responseStream.Close();
response.Close();
});
}
私有静态无效TimeoutCallback(对象状态,布尔TIMEDOUT)
{
Console.WriteLine(超时:+ TIMEDOUT);
如果(TIMEDOUT)
{
Console.WriteLine(超时);
WebRequest的要求=(WebRequest的)状态;
如果(状态!= NULL)
{
request.Abort();
}
}
}
}
和我测试的类与此code:
类节目
{
静态无效的主要(字串[] args)
{
//发出请求到一个不存在的域。
HttpSocket.MakeRequest(新的URI(HTTP://www.google.comhklhlñ),callbackState =&GT;
{
如果(callbackState.Exception!= NULL)
扔callbackState.Exception;
Console.WriteLine(GetResponseText(callbackState.ResponseStream));
});
Thread.sleep代码(100000);
}
公共静态字符串GetResponseText(流responseStream)
{
使用(VAR读卡器=新的StreamReader(responseStream))
{
返回reader.ReadToEnd();
}
}
}
一旦执行,回调马上达到,显示超时:假,有没有更多的罚球,让超时工作不
这是在原来的线程提出了一个解决方案,但是,因为你可以看到中,code为他工作。
我在做什么错了?
编辑:使用的code。其他类:
类RequestCallbackState
{
公共流ResponseStream {获得;私定; }
公共异常异常{获得;私定; }
公共RequestCallbackState(流responseStream)
{
ResponseStream = responseStream;
}
公共RequestCallbackState(例外的例外)
{
异常=例外,
}
}
类RequestState
{
公共字节[] RequestBytes {获得;组; }
公众的WebRequest请求{获得;组; }
公益行动&LT; RequestCallbackState&GT; ResponseCallback {获得;组; }
}
解决方案
此方法效果。我会建议切换这明确地处理异常情况(包括你超时,但也很糟糕域名等)略有不同。在这种情况下,我这个分裂成一个单独的延续。
此外,为了使这个非常明确,我已经短的超时时间,把一个真正的,但是进展缓慢域,因为增加了一个明确的暂停状态,你可以看到,以及:
使用系统;
使用System.IO;
使用System.Net;
使用的System.Threading;
使用System.Threading.Tasks;
类HttpSocket
{
私人const int的TimeoutLength = 100;
公共静态无效MakeRequest(URI URI,动作&LT; RequestCallbackState&GT; responseCallback)
{
WebRequest的请求= WebRequest.Create(URI);
request.Proxy = NULL;
任务&LT; WebResponse的&GT; AsyncTask的= Task.Factory.FromAsync&LT; WebResponse的&GT;(request.BeginGetResponse,request.EndGetResponse,NULL);
ThreadPool.RegisterWaitForSingleObject((AsyncTask的为IAsyncResult的).AsyncWaitHandle,新WaitOrTimerCallback(TimeoutCallback),要求TimeoutLength,真正的);
asyncTask.ContinueWith(任务=&GT;
{
WebResponse的响应= task.Result;
流responseStream = response.GetResponseStream();
responseCallback(新RequestCallbackState(response.GetResponseStream()));
responseStream.Close();
response.Close();
},TaskContinuationOptions.NotOnFaulted);
//处理错误
asyncTask.ContinueWith(任务=&GT;
{
VAR例外= task.Exception;
VAR webException = exception.InnerException;
//跟踪您是否取消或不...给你...
responseCallback(新RequestCallbackState(exception.InnerException,webException.Message.Contains(请求被取消。)));
},TaskContinuationOptions.OnlyOnFaulted);
}
私有静态无效TimeoutCallback(对象状态,布尔TIMEDOUT)
{
Console.WriteLine(超时:+ TIMEDOUT);
如果(TIMEDOUT)
{
Console.WriteLine(超时);
WebRequest的要求=(WebRequest的)状态;
如果(状态!= NULL)
{
request.Abort();
}
}
}
}
类RequestCallbackState
{
公共流ResponseStream {获得;私定; }
公共异常异常{获得;私定; }
公共BOOL请求超时{获得;私定; }
公共RequestCallbackState(流responseStream)
{
ResponseStream = responseStream;
}
公共RequestCallbackState(例外的例外,布尔TIMEDOUT = FALSE)
{
异常=例外,
请求超时= TIMEDOUT;
}
}
类RequestState
{
公共字节[] RequestBytes {获得;组; }
公众的WebRequest请求{获得;组; }
公益行动&LT; RequestCallbackState&GT; ResponseCallback {获得;组; }
}
类节目
{
静态无效的主要(字串[] args)
{
//发出请求到一个不存在的域。
HttpSocket.MakeRequest(新的URI(http://www.tanzaniatouristboard.com/),callbackState =&GT;
{
如果(callbackState.RequestTimedOut)
{
Console.WriteLine(暂停!);
}
否则,如果(callbackState.Exception!= NULL)
扔callbackState.Exception;
其他
Console.WriteLine(GetResponseText(callbackState.ResponseStream));
});
Thread.sleep代码(100000);
}
公共静态字符串GetResponseText(流responseStream)
{
使用(VAR读卡器=新的StreamReader(responseStream))
{
返回reader.ReadToEnd();
}
}
}
这将运行,并适当地显示超时。
I asked this question before but I'm going to complete the question with a solution proposed and make another question.
I'm using this class to make an async 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();
}
}
}
}
And i'm testing the class with this code:
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();
}
}
}
Once executed, the callback is reached immediately, showing "Timeout: false" and there aren't more throws, so the timeout isn't working.
This is a solution proposed in the original thread but, as you could see, the code works for him.
What I'm doing wrong?
EDIT: Other classes used by the code:
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; }
}
解决方案
This approach works. I would recommend switching this to explicitly handle exceptions (including your timeout, but also bad domain names, etc) slightly differently. In this case, I've split this into a separate continuation.
In addition, in order to make this very explicit, I've shorted the timeout time, put a "real" but slow domain in, as well as added an explicit timeout state you can see:
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();
}
}
}
This will run, and show a timeout appropriately.