HttpClient.SendAsync使用线程池而不是异步IO?所以我一直在通过Reflector挖掘HttpClient.SendAsync的实现。我感兴趣的是这些方法的执行流程,以及确定调用哪个API来执行异步IO工作。在探索了HttpClient的各个类之后,我在内部看到它使用了HttpClientHandler,它派生自HttpMessageHandler并实现了它的SendAsync方法。这是HttpClientHandler.SendAsync的现实:protectedinternaloverride}this.CheckDisposed();这个.SetOperationStarted();TaskCompletionSourcesource=newTaskCompletionSource();RequestStatestate=newRequestState{tcs=source,cancellationToken=cancellationToken,requestMessage=request};尝试{HttpWebRequestrequest2=this.CreateAndPrepareWebRequest(request);state.webRequest=request2;cancellationToken.Register(onCancel,request2);如果(ExecutionContext.IsFlowSuppressed()){IWebProxyproxy=null;如果(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.start请求,状态);}catch(Exception异常){this.HandleAsyncException(state,exception);}返回源。任务;我觉得很奇怪,上面使用Task.Factory.StartNew生成TaskCompletionSource并返回由它创建的任务执行请求为什么这对我来说很奇怪?好吧,让我们继续讨论I/O绑定异步操作如何在幕后不需要额外的线程,以及它如何与IO重叠。为什么要使用Task.Factory.StartNew来触发异步I/O操作?这意味着SendAsync不仅使用纯异步控制流执行此方法,而且还会“在我们后面”旋转ThreadPool线程来完成它的工作。this.startRequest是一个指向this.startRequest的委托,后者又使用HttpWebRequest.BeginGetResponse来启动异步IO。HttpClient在幕后使用异步IO,仅包装在线程池任务中。也就是说,请注意SendAsync//BeginGetResponse/BeginGetRequestStream的以下注释在成为异步之前需要做很多设置工作//(代理、dns、连接池等)。在单独的线程上运行这些。//不要提供取消标记;如果这个辅助任务可以在开始之前取消,那么//没有人会完成tcs.Task.Factory.StartNew(startRequest,state);这解决了HttpWebRequest的一个众所周知的问题:它的一些处理阶段是同步的。这是API的缺陷。HttpClient通过将DNS工作移至线程池来避免阻塞。是好还是坏?这很好,因为它使HttpClient成为非阻塞的并且适合在UI中使用。这很糟糕,因为我们现在将线程用于长时间运行的阻塞工作,即使我们根本不希望使用线程。这会降低使用异步IO的好处。事实上,这是混合同步和异步IO的一个很好的例子。使用两者本质上没有错。HttpClient和HttpWebRequest正在使用异步IO进行长时间运行的阻塞工作(HTTP请求)。他们使用线程进行短期工作(DNS,...)。总的来说,这不是一个糟糕的模式。我们避免了大部分的阻塞,我们只需要将一小部分代码做成异步的。典型的80-20权衡。在BCL(库)中找到这样的东西并不好,但在应用程序级代码中,它可能是一个非常明智的权衡。似乎最好修复HttpWebRequest。出于兼容性原因,这可能是不可能的。以上就是C#学习教程:HttpClient.SendAsyncusingthreadpoolinsteadofasynchronousIO?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
