2012-07-29 30 views
17

这是我上周正在调查的问题,找不到任何解决方法。找到相同的帖子,但从来没有得到答案,希望这也会帮助其他人。如何从WCF服务中止流而不读取结束?

我有一个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

这是什么运气? – Schultz9999 2013-02-05 18:59:56

+0

发送真正大文件时遇到同样的问题...似乎必须错过一些非常明显的东西。我可能将不得不实施分块作为解决方法。 – 2013-02-14 14:23:12

回答

0

你试过玩binding.MaxBufferSize吗?
您是否尝试过玩弄你的app.config文件设置e.g:

<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> 

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

+1

我试过了,但没有帮助。一旦服务器开始发送流,它不会停止,直到客户端收到它。关闭代理服务器不会执行任何操作。 这似乎没有明显的方式来阻止沟通。 当客户端停止读取流时,我可以看到tcp窗口零返回到服务器。并且服务器定期发送一个窗口零探针来查看客户端是否准备好再次读取。当然,客户端再次发回窗口零。 这一直持续下去,直到过程被杀死。 – Yev 2012-08-01 14:14:01

+0

您是否试过仅使用HttpClient Class读取流,并查看是否可以关闭流? – 2012-08-01 18:19:40

+0

如何在不调用WCF服务的情况下执行此操作? 我已经做了一些更多的研究,似乎没有办法从客户端关闭流。 我尝试了一种不同的方法。我创建了另一个服务,一个控制服务,并尝试从那里关闭流(服务器端)。但没有运气。有些东西不起作用,它不会关闭或处置。 – Yev 2012-08-01 18:26:26

1

调查后,我发现,WCF客户端将继续阅读从流,直到closeTimeout ellapsed,然后将中止连接。您可能会减少客户端的closeTimeout以最小化问题。

注意:您应该将配置流的代码封装到try/catch块中。 stream.Dispose()方法会抛出TimeoutException,这会制动not throwing exceptions in Dispose method的准则。

0

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

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

我在这个问题上的测试涉及到我编写一个NeverEndingStream并始终返回数据。在某些时候,我打电话给客户端,然后几乎立即关闭了服务器。这表明缓冲区仅仅是空的,因为显然它永远不会读到我的流到最后。

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

相关问题