【发布时间】:2014-07-27 17:34:53
【问题描述】:
所以我一直在研究通过 Reflector 实现 HttpClient.SendAsync。我特意想了解这些方法的执行流程,并确定调用哪个 API 来执行异步 IO 工作。
在探索了HttpClient 内部的各种类之后,我看到它在内部使用了HttpClientHandler,它派生自HttpMessageHandler 并实现了它的SendAsync 方法。
这是HttpClientHandler.SendAsync的实现:
protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException("request", SR.net_http_handler_norequest);
}
this.CheckDisposed();
this.SetOperationStarted();
TaskCompletionSource<HttpResponseMessage> source = new TaskCompletionSource<HttpResponseMessage>();
RequestState state = new RequestState
{
tcs = source,
cancellationToken = cancellationToken,
requestMessage = request
};
try
{
HttpWebRequest request2 = this.CreateAndPrepareWebRequest(request);
state.webRequest = request2;
cancellationToken.Register(onCancel, request2);
if (ExecutionContext.IsFlowSuppressed())
{
IWebProxy proxy = null;
if (this.useProxy)
{
proxy = this.proxy ?? WebRequest.DefaultWebProxy;
}
if ((this.UseDefaultCredentials || (this.Credentials != null)) || ((proxy != null) && (proxy.Credentials != null)))
{
this.SafeCaptureIdenity(state);
}
}
Task.Factory.StartNew(this.startRequest, state);
}
catch (Exception exception)
{
this.HandleAsyncException(state, exception);
}
return source.Task;
}
我觉得奇怪的是,上面使用Task.Factory.StartNew 执行请求,同时生成一个TaskCompletionSource<HttpResponseMessage> 并返回由它创建的Task。
为什么我觉得这很奇怪?好吧,我们继续讨论 I/O 绑定的异步操作如何在幕后不需要额外的线程,以及它是如何与重叠 IO 相关的。
为什么要使用Task.Factory.StartNew 来触发异步 I/O 操作?这意味着SendAsync 不仅使用纯异步控制流来执行此方法,而且还旋转一个 ThreadPool 线程“在我们背后” 来执行它的工作。
【问题讨论】:
标签: c# asynchronous task-parallel-library dotnet-httpclient