我正在根据question上接受的答案实施代码。现在我遇到一个问题,看起来线程处于打开状态:应用程序永远不会完成。
我认为这可能是由于下面ThreadPool.RegisterWaitForSingleObject
的两个出现的最后一个引起的。第一个监听WebRequest完成或超时发生。第二个监听被请求的取消。现在我想知道:如果没有要求取消或者它会一直等待,第二个会完成吗?
public static Task<WebResponse> GetResponseAsync(this WebRequest request, CancellationToken token)
{
if (request == null)
throw new ArgumentNullException("request");
bool timeout = false;
TaskCompletionSource<WebResponse> completionSource = new TaskCompletionSource<WebResponse>();
AsyncCallback completedCallback =
result =>
{
try
{
completionSource.TrySetResult(request.EndGetResponse(result));
}
catch (WebException ex)
{
if (timeout)
completionSource.TrySetException(new WebException("No response was received during the time-out period for a request.", WebExceptionStatus.Timeout));
else if (token.IsCancellationRequested)
completionSource.TrySetCanceled();
else
completionSource.TrySetException(ex);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
};
IAsyncResult asyncResult = request.BeginGetResponse(completedCallback, null);
if (!asyncResult.IsCompleted)
{
if (request.Timeout != Timeout.Infinite)
{
WaitOrTimerCallback timedOutCallback =
(object state, bool timedOut) =>
{
if (timedOut)
{
timeout = true;
request.Abort();
}
};
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle, timedOutCallback, null, request.Timeout, true);
}
if (token != CancellationToken.None)
{
WaitOrTimerCallback cancelledCallback =
(object state, bool timedOut) =>
{
if (token.IsCancellationRequested)
request.Abort();
};
ThreadPool.RegisterWaitForSingleObject(token.WaitHandle, cancelledCallback, null, Timeout.Infinite, true);
}
}
return completionSource.Task;
}
答案 0 :(得分:2)
是的,线程池将等待取消令牌的等待句柄无限期地发出信号。
您需要保存RegisterWaitForSingleObject()
的返回值才能取消未完成的等待操作。请参阅ThreadPool.RegisterWaitForSingleObject备注部分,因为它表明您应始终取消注册等待。
优秀的等待操作不应该使你的过程保持活跃。