给出如下操作:
public void DoSomething()
{
IWcfServiceAgentAsync agent = new WcfServiceAgentProxy();
var request = new DoSomethingRequest();
agent.BeginDoSomething(request,
iar =>
{
var response = agent.EndDoSomething(iar);
/*
* Marshal back on to UI thread with results
*/
}, null);
}
在操作开始和执行回调之间,什么是真正在幕后?是否有接收轮询的套接字等待完成?是否有一个底层的OS线程在它返回之前被阻塞?
答案 0 :(得分:3)
BeginDoSomething
最终会在WCF代理上调用base.Channel.BeginGetTest(callback, asyncState);
。那个代理然后做的是通过" Binding Stack"的每个部分。您已为WCF通信进行了设置。
您的请求将通过的绑定堆栈的一个主要部分是" Message Encoder"。消息编码器将您的请求打包成可以表示为byte[]
的内容(此过程称为序列化)。
通过邮件编码器后,您的请求将发送到Transport(无论是HTTP,TCP还是其他内容)。传输采用byte[]
并将其发送到目标端点,然后告诉操作系统"当您收到针对我的响应时,请调用此功能"通过IO Completion Ports系统。 (我将假设TCP或HTTP绑定用于此答案的其余部分)(编辑:注意,IO完成端口不必使用,由传输层决定该怎么做,只是框架内置的大部分实现都将使用那个)
在您的消息发送和收到响应之间的时间内没有线程,没有极化,没有任何发生。当网卡收到响应时,它会发出一个中断,告诉操作系统它有新信息,该中断被处理,最终操作系统发现它是用于你的应用程序的几个字节的数据。然后,操作系统会告诉您的应用程序启动IOCP线程池线程并将其传递给接收到的几个字节的数据。
(参见" There is no Thread"由Stephen Cleary提供有关此过程的更多信息。它在谈论TPM而不是像您的示例中的APM,但底层是完全相同的。)
当接收到来自另一台计算机的字节时,这些字节以相反的方向返回堆栈。 IOCP线程从Transport运行一个函数,它接收传递给它的字节并将其交给Message Encoder。这个动作可能会发生几次!
消息编码器从传输中接收字节并尝试构建消息,如果没有接收到足够的字节,它只是将它们排队并等待传入下一组字节。一旦它有足够的字节为了使消息脱离化,它将创建一个新的响应"对象并将其设置为IAsyncResult
的结果,然后(我不确定是谁,可能是WCF调用堆栈,它可能是.NET中的其他位置)看到您的IAsyncResult
有一个回调委托并启动另一个IOCP线程,该线程是您的委托运行的线程。