Task fromAsync timeout
本文关键字:timeout fromAsync Task | 更新日期: 2023-09-27 18:08:03
我有这段代码来发出异步HTTP请求:
public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task =>
{
WebResponse response = task.Result;
Stream responseStream = response.GetResponseStream();
responseCallback(new RequestCallbackState(response.GetResponseStream()));
responseStream.Close();
response.Close();
});
}
它工作,但我需要设置一个请求超时。我试着用请求。暂停,但似乎没有做任何事情。在此代码中是否有方法设置任务超时?
编辑添加一个新的超时回调。新代码:
public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
IAsyncResult t = Task.Factory.FromAsync<WebResponse>(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<Stream> responseCallback)
{
WebRequest request = WebRequest.Create(uri);
request.Proxy = null;
const int TimeoutPeriod = 1000;
Task<WebResponse> t = Task.Factory.FromAsync<WebResponse>(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();
});
}
这对我来说很有效(如果我把超时时间设置得很短,然后点击这个,我总是会适当地超时)。