17

这是我上周一直在调查的问题,但找不到任何解决方案。发现帖子问同样的问题,但从未得到答案,希望这对其他人也有帮助。

我有一个WCF服务,它返回一个包含 a 的对象stream。我使用basicHttpBinding流传输和 Mtom 将其发送到客户端。

WCF客户端在收到响应对象后立即调用服务并关闭代理。

接下来,客户端读取从 WCF 服务获得的流并将其写入本地磁盘上的文件。所有这一切都很好。

我的问题是当客户端想要中止操作并停止从 WCF 服务下载数据时。如果我调用.close()流,例如:serverReply.DataStream.Close();然后它会阻塞并从 WCF 服务读取整个流,直到它结束,然后再继续。流可能非常大,网络并不总是很快。

这对于网络资源的使用都是非常不利的,这基本上浪费在不再使用的数据上。并且由于basicHttpBinding只允许到 WCF 服务服务器的两个并发 TCP 连接(默认情况下),它会阻止其他连接尝试,直到流被读取直到结束。

我可以增加并发连接的数量,但这将是一个糟糕的解决方案,因为它会造成麻烦。

例如,20 个中止的下载仍在下载数据以将其丢弃。我需要完全停止传输。

在客户端,流对象只是一个普通的Stream类,所以它只有 close 方法,没有别的。

调用.close().abort()代理对象没有帮助,使用.dispose()或任何其他方法破坏它也无济于事。在服务器端,我处理该OperationContext.OperationCompleted事件,但直到从 数据stream读取到最后才会触发它。

所以问题是,我如何在不完全阅读的情况下关闭/中止流?

4

3 回答 3

1

经过调查,我发现 WCF 客户端将继续从流中读取,直到 closeTimeout 结束,然后它将中止连接。您可以减少客户端上的 closeTimeout 以最小化问题。

注意:您应该将处理流的代码包装到 try/catch 块中。stream.Dispose() 方法将抛出 TimeoutException ,这打破了在 Dispose 方法中不抛出异常的准则。

于 2014-08-12T14:52:04.010 回答
0

我认为您只是在关闭后收到缓冲区。您应该将 maxBufferSize 设置为较低的值。

您可能还希望通过包装流和覆盖读取来限制服务器上读取的数据量。如果您的客户端带宽较低,请使用较小的块,并从 read 方法返回相应的计数以匹配您实际读取的数量。这将限制缓冲区的填充率。

我自己对此主题的测试涉及我编写一个 NeverEndingStream 并始终返回数据。在某些时候,我在客户端上调用了关闭,然后几乎立即在服务器上调用了关闭。这表明缓冲区只是被清空了,因为很明显它直到最后都无法读取我的流。

如果您仍然遇到问题,那么我建议您在覆盖的流上跟踪 Read 方法的时间。如果 currentReadtime - the lastReadTime > x 那么您可以改为调用 Close 并引发异常。那肯定会杀了它。

于 2015-02-26T09:19:30.873 回答
0

你试过玩弄binding.MaxBufferSize吗?
您是否尝试过使用您的 app.config 文件设置,例如:

<bindings>
  <wsHttpBinding>
    <binding name="default" maxReceivedMessageSize="2147483647"  maxBufferPoolSize="2147483647" 
             closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" >
      <readerQuotas  maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384"
                     maxDepth="64" maxStringContentLength="2147483647" />
    </binding>

  </wsHttpBinding>
</bindings>

我会尽量减少超时和缓冲区长度,并尝试中止或关闭,看看会发生什么。

于 2012-07-31T18:22:27.967 回答