C# 如何中止WCF服务中的流而不将其读取到底?
这是我上周一直在调查的问题,但找不到任何解决方案。找到了问同样问题但从未得到答案的帖子,希望这也能帮助其他人 我有一个C# 如何中止WCF服务中的流而不将其读取到底?,c#,wcf,stream,wshttpbinding,mtom,C#,Wcf,Stream,Wshttpbinding,Mtom,这是我上周一直在调查的问题,但找不到任何解决方案。找到了问同样问题但从未得到答案的帖子,希望这也能帮助其他人 我有一个WCF服务,它返回一个包含流的对象。我使用basicHttpBinding和流式传输和Mtom将其发送到客户端 客户端调用WCF服务,并在收到响应对象后立即关闭代理 接下来,客户端读取从WCF服务获得的流,并将其写入本地磁盘上的文件。所有这些都很好 我的问题是当客户端想要中止操作并停止从WCF服务下载数据时。 如果我在流上调用.close(),例如:serverReply.Dat
WCF
服务,它返回一个包含流的对象。我使用basicHttpBinding
和流式传输和Mtom将其发送到客户端
客户端调用WCF
服务,并在收到响应对象后立即关闭代理
接下来,客户端读取从WCF服务获得的流,并将其写入本地磁盘上的文件。所有这些都很好
我的问题是当客户端想要中止操作并停止从WCF服务下载数据时。
如果我在流上调用.close()
,例如:serverReply.DataStream.close()
然后它阻塞并读取来自WCF服务的整个流,直到其结束,然后继续。流可能相当大,并且网络并不总是很快
这对于网络资源的使用都是非常不可取的,这基本上是浪费在不再有用的数据上。由于basicHttpBinding
只允许到WCF服务服务器的两个并发TCP连接(默认情况下),因此它会阻止其他连接尝试,直到读取流为止
我可以增加并发连接的数量,但这将是一个糟糕的解决方案,因为它会给麻烦制造一个机会
例如,20次中止的下载仍在下载数据以将其丢弃。我需要让转车完全停止
在客户机上,stream对象只是一个常规的stream
类,因此它只有close方法,没有其他方法
在代理对象上调用.close()
或.abort()
没有帮助,使用.dispose()
或任何其他方法销毁它也没有帮助。
在服务器端,我处理OperationContext.OperationCompleted
事件,但直到从流
读取数据为止,它不会被触发
所以问题是,如何在不完全读取流的情况下关闭/中止流?您是否尝试过使用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>
我会尽量减少超时和缓冲区长度,并尝试中止或关闭,看看会发生什么。经过调查,我发现WCF客户端将一直从流中读取数据,直到关闭超时终止,然后它将中止连接。您可以减少客户端上的closeTimeout以将问题最小化
注意:您应该将处理流的代码包装到try/catch块中。stream.Dispose()方法将抛出TimeoutException,它会阻止一条规则。我认为您只是在关闭后接收缓冲区。应将maxBufferSize设置为较低的值
您可能还希望通过包装流和覆盖读取来限制服务器上读取的数据量。如果您的客户端带宽较低,请使用较小的数据块,并从read方法返回相应的计数,以匹配您实际读取的数据量。这将限制缓冲区的填充率
我自己在这方面的测试包括我编写一个永不中断的流,并始终返回数据。在某个时候,我在客户端上调用了close,然后几乎立即在服务器上调用了close。这表明缓冲区只是被清空了,因为很明显,它永远无法读取我的流,直到最后
如果您仍然遇到问题,那么我建议您跟踪重写流上Read方法的计时。如果currentReadtime-lastReadTime大于x,则可以调用Close并引发异常。那肯定会杀了它 我试过了,但没用。一旦服务器开始发送流,它不会停止,直到客户端接收到所有流。关闭代理不起任何作用。好像没有明显的方法来阻止交流。当客户端停止读取流时,我可以看到tcp窗口0返回到服务器。服务器定期发送一个windowzero探测,以查看客户端是否准备好再次读取。当然,客户端再次发送回窗口0。这将一直持续到进程被终止。您是否尝试过仅使用HttpClient类读取流,并查看是否可以关闭流?如何在不调用WCF服务的情况下关闭流?我做了更多的研究,似乎没有办法从客户端关闭流。我尝试了另一种方法。我创建了另一个服务,一个控制服务,并试图从那里关闭流(服务器端)。但是没有运气。有些东西不工作,无法关闭或处理。在发送非常大的文件时遇到同样的问题。。。看来一定是遗漏了一些很明显的东西。我可能不得不将分块作为一种解决方法。