这是我上周一直在调查的问题,无法找到任何解决方案。发现帖子提出同样但从未得到答案,希望这也会对其他人有所帮助。
我有一个WCF
服务,它返回一个包含stream
的对象。我使用basicHttpBinding
进行流式传输和Mtom将其发送给客户端。
客户端调用WCF
服务并在收到响应对象后立即关闭代理。
接下来,客户端读取从WCF服务获取的流并将其写入本地磁盘上的文件。所有这一切都很好。
我的问题是客户端想要中止操作并停止从WCF服务下载数据。
如果我在流上调用.close()
,例如:serverReply.DataStream.Close();
则它会阻止并从WCF服务读取整个流,直到结束,然后继续。流可能非常大,网络并不总是很快。
这对于两种网络资源的使用都是非常不受欢迎的,这基本上浪费在不再使用的数据上。由于basicHttpBinding
仅允许两个并发TCP连接(默认情况下)到WCF服务服务器,因此它会阻止其他连接尝试,直到读取流直到结束。
我可以增加并发连接的数量,但这将是一个糟糕的解决方案,因为它会为麻烦创建一个开放。
例如,20个中止的下载仍在下载数据以将其丢弃。我需要完全停止转移。
在客户端上,流对象只是一个普通的Stream
类,所以它只有close方法,没有别的。
在代理对象上调用.close()
或.abort()
没有帮助,也没有使用.dispose()
或任何其他方法销毁它。
在服务器端,我处理OperationContext.OperationCompleted
事件,但在读取stream
的数据直到结束时才会触发。
所以问题是,如何关闭/中止流而不完全读取它?
答案 0 :(得分:1)
经过调查,我发现WCF客户端将继续从流中读取,直到closeTimeout被删除,然后它将中止连接。您可以减少客户端上的closeTimeout以最小化问题。
注意:您应该将处理流的代码包装到try / catch块中。 stream.Dispose()方法将抛出TimeoutException,它会制定not throwing exceptions in Dispose method的准则。
答案 1 :(得分: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>
我会尽量减少缓冲区长度的超时,并尝试中止或关闭,看看会发生什么。
答案 2 :(得分:0)
我认为你只是在关闭后才收到缓冲区。您应该将maxBufferSize设置为较低的值。
您可能还希望通过包装流并覆盖读取来限制服务器上读取的数据量。如果您的带宽较低的客户端使用较小的块,并从read方法返回相应的计数以匹配您实际读取的数量。这会限制缓冲区的填充率。
我对这个主题的测试涉及到我编写NeverEndingStream并始终返回数据。在某些时候,我在客户端上调用close,然后几乎立即在服务器上调用了close。这表明缓冲区只是被清空了,因为显然它永远无法读到我的流直到最后。
如果您仍遇到问题,我建议您在已覆盖的流上跟踪Read方法的时间。如果currentReadtime - lastReadTime是&gt; x然后你可能会调用Close并抛出异常。这肯定会杀了它。