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服务的情况下关闭流?我做了更多的研究,似乎没有办法从客户端关闭流。我尝试了另一种方法。我创建了另一个服务,一个控制服务,并试图从那里关闭流(服务器端)。但是没有运气。有些东西不工作,无法关闭或处理。在发送非常大的文件时遇到同样的问题。。。看来一定是遗漏了一些很明显的东西。我可能不得不将分块作为一种解决方法。