操作(Operation)

      WCF提供了三种调用模式:请求-应答操作,单向操作,回调操作。

      请求-应答操作

      默认情况下,WCF采用请求-应答模式。客户端以消息形式发出请求,它会阻塞客户端直到收到应答消息。所有的WCF绑定均支持请求-应答操作。

      单向操作

      单向操作时,操作没有返回值,客户端也不关心调用成功与否。服务端抛出的任何异常都不会传递给客户端。单向调用并不等同于异步调用。当单向调用到达服务端是,不会立即分发这些调用,而是可能放到服务端的队列中,并在某个时间被分发。所有的WCF绑定均支持单向操作。

      回调操作

      回调操作时,服务端可以调用客户端。客户端必须为回调对象的托管提供易于实现的机制。回调操作尤其适用于事件,在服务端触发事件时使用回调操作通知客户端。只有具有双向能力的绑定才能够用于回调。包括:nettcp,netnamedpipe,wsdualhttp。

      回调操作是服务契约的一部分,它取决于服务契约对回调契约的定义。一个服务契约最多只能包含一个回调契约。一点定义了回调契约,就需要客户端支持回调,并在每次调用中提高指向服务的回调终结点。

      客户端负责托管回调对象以及公开回调终结点。服务实例最内层的执行范围是实例上下文。InstanceContext类定义的构造函数,能够将服务实例传递给宿主。为了托管一个回调对象,客户端需要实例化回调对象,然后通过它创建一个上下文对象。注意,虽然回调方法是在客户端,但他们仍然属于WCF操作,因此他们都包含在了一个操作上下文中,可以通过OperationContext.Current访问。

      只要服务端终结点的契约定义了一个回调契约,在与它进行交互时,客户端都必须使用代理创建双向通信,并将回调终结点的引用传递给服务。客户端的代理需继承自DuplexClientBase<T>类。

      服务如何处理回调应用以及如何决定使用它,完全有服务抉择。服务能够从操作上下文中提取出回调引用,然后将他保存起来以待今后的使用;或者可以在服务运行期间使用它将调用返回给客户端。

      在使用回调服务时,服务默认为单线程并发模式。最常见的问题是死锁。解决方案主要有一下三种:1、将服务配置为允许多线程访问,并发模式为Multiple;2、将服务配置为可重入的。并发模式为Reentrant。3、将回调契约配置为单向操作。

      关于回调连接的管理。当服务维持了一个回调终结点上的引用,而此时客户端代理关闭或者退出,如果服务进行回调,就会出现ObjectDisposedException异常。因此,客户端应该决定自己何时加入和退出自己。在不需要服务时,能够通知服务端删除回调引用。

      关于回调端口。

      在使用NetTcpBinding和NetNamedPipeBinding时,回调通过绑定所维护的输出通道进入客户端,然后到达服务。它不需要打开一个新的端口或通道。而使用WSDualHttpBinding时,WCF专门为回调维护了一个单独的HTTP通道,因为HTTP自身属于单向协议。WCF为回调选择了默认的80端口,并将使用HTTP的回调地址、客户端机器名以及端口号80传递给服务。通常基于Internet的服务会使用80端口,如果机器运行了IIS,80端口就会被占用,客户端将无法托管回调终结点。在WSDualHttpBinding绑定中,WCF提供了ClientBaseAddress属性,可以为客户端配置不同的回调URI。我们也可以通过编程的方式动态生成可用的回调接口。

      关于事件。在双向回调中,相对于回调操作,WCF更重视的是事件的运用。建议将事件分解为单独的回调契约,而不要在相同的契约中将事件和常规调用混合在一起。

      关于流操作。

      在默认情况下,当客户端和服务器端交换消息时,这些消息会放入接收端的缓存中,一旦 接收到了完整的消息,就会立即被传递。对于数据量小的消息,这种交换模式提供了简单的编程模型,因为接受消息的耗时较之处理消息本身而言微不足道。但是对于数据量较大的消息,如包含了多媒体内容、大文件或数据块,如果每次都要等到完整的接受到消息后,才能解除阻塞,则不现实。为了解决这种问题,WCF允许接收端通过通道接收消息的同时,启动对消息数据的处理。也就是流传输模型。

      支持流传输的绑定主要有:BasicHttpBinding,NetTcpBinding,NetNamedPipeBinding。开通流传输,需要将传输模式设置为TransferMode.Streamed。

      当发送端发出流消息时,发送端并不知道接收端何时使用流进行操作。这样发送端就无法关闭流,因此关闭流应该由服务端使用完毕后负责关闭。

       几点注意:首先开发者需要同步访问流的内容。如采取只读方式等。此外,不要对会话服务使用流操作,因为流操作可能会持续相当长时间,而会话则不同,它意味着一个锁步执行(Lock-Step)执行,同时具有一个良好设计的会话分界。

原文地址:https://www.cnblogs.com/jyz/p/1449647.html