0

我正在从这个问题的公认答案中实现代码。现在我遇到了一个问题,看起来好像线程处于打开状态:应用程序永远不会完成。

我认为这可能是由以下两种情况之一引起的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;
}
4

1 回答 1

2

是的,线程池将无限期地等待取消令牌的等待句柄发出信号。

您需要保存的返回值RegisterWaitForSingleObject()才能取消未完成的等待操作。请参阅ThreadPool.RegisterWaitForSingleObject备注部分,因为它表明您应该始终取消注册等待。

但是,未完成的等待操作不应使您的进程保持活动状态。

于 2013-10-15T02:57:28.570 回答