WCF中的Stream操作

翻译|其它|编辑:郝浩|2007-12-10 10:12:15.000|阅读 908 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

      WCF 支持对 Stream 对象的操作,尤其对于传递 size 过大的消息而言,如要考虑传递消息的效率,WCF 推荐通过 Stream 进行操作。

      然而,WCF 对于 Stream 操作规定了一些限制,在我们编写相关程序时,需要特别注意:

      1、绑定的限制

      如果需要使用 Stream 操作,可以使用的绑定只能是 BasicHttpBinding,NetTcpBinding 以及 NetNamedPipeBinding。此外,在使用 Stream 操作时,不能使用 Reliable Messaging。如果考虑到消息安全,则此方式是不可取的。

      2、对 Stream 对象的限制

      要作为服务操作所传递的消息对象,这样的对象必须是可序列化的。遗憾的是,FileStream 类的定义却是不支持序列化的,我们能够使用的 Stream 对象,包括 Stream,MemoryStream 等。使用 Stream 类对象是大多数 Stream 操作的首选。

      一个有趣的现象是 FileStream 与 Stream 类型的转换。例如在服务契约的操作中,有如下的实现:
public Stream TransferDocument(Document document)
{
     FileStream stream = new FileStream
                             (document.LocalPath, FileMode.Open, FileAccess.Read);
     return stream;
}
      注意,操作 TransferDocument()的返回类型为 Stream,而方法的实现中,返回的对象则为 FileStream 类型。由于 Stream 类是 FileStream 类的父类,这样的实现没有问题。

      然而,在客户端调用该操作时,却不能将操作的返回值赋给 FileStream 类型的对象,如下所示:

      FileStream stream = m_service.TransferDocument(doc);

      此时获得的 Stream 对象则为 null。因而,我们只能这样调用操作:

      Stream stream = m_service.TransferDocument(doc);

      但是,还有一个奇怪的问题是 WCF 并不支持 Stream 对象 Length 属性的序列化,也就是说,在客户端我们不能使用服务操作返回的 Stream 对象的 Length 属性。诸如 stream.Length 的调用会抛出 NotSupportedException 异常。

      3、TransferMode 的限制

      若要使用 Stream 操作,必须修改绑定的 TransferMode 属性。该属性的默认值为 Buffered。我们应该根据操作中 Stream 对象的参数类型,以决定 TransferMode 的值分别为 Streamed、StreamedRequest 或者 StreamedResponse。

      4、MaxReceivedMessageSize 的限制

      MaxReceivedMessageSize 属性的默认值为64kb,如果传递的 Stream 对象一旦超过了 MaxReceivedMessageSize 属性的设置值,则客户端在操作该对象时,就会出现 CommunicationException 异常。因此,我们应根据实际需要设置 MaxReceivedMessageSize 的值。MaxReceivedMessageSize 属性的取值范围为1-9223372036854775807(Int32.MaxValue)。如果设置值不在该范围之内,则无法通过编译。编程方式设置为:
binding.MaxReceivedMessageSize = 120000;
配置文件的设置方式为:
<binding …… maxReceivedMessageSize="120000"/>

      5、操作参数的限制

      WCF 对包含了 Stream 对象的操作参数进行严格的限制,它只允许这样的操作只能包含一个 Stream 对象,这里所谓的一个 Stream 对象,是包含 return 对象,out 和 ref 对象在内的。也就是说如下的操作定义都是错误的:
      void Transfer(Stream s1, Stream s2);
      void Transfer(Stream s1, out Stream s2);
      void Transfer(Stream s1, ref Stream s2);
      Stream Transfer(Stream stream);
      如果定义了这样的操作,则会出现运行时错误。

      此外,由于传输的 Stream 对象较大,可能会消耗过长的时间,因而建议增大绑定的 SendTimeout 属性值。例如设置为10分钟。编程方式设置为:
      binding.SendTimeout = TimeSpan.FromMinutes(10);
      配置文件的设置方式为:
      <binding …… sendTimeout="00:10:00"/>
      注意,对绑定的相关设置必须要求服务端与客户端的配置一致。最佳实践是均通过配置文件进行设置。例如在我的应用程序中是这样设置的:
<basicHttpBinding>
        <binding name="DocumentExplorerServiceBinding"
                 sendTimeout="00:10:00"
                 transferMode="Streamed"
                 messageEncoding="Text"
                 textEncoding="utf-8"
                 maxReceivedMessageSize="9223372036854775807">         
        binding>
basicHttpBinding>


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP