2012-07-29 31 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並引發異常。這肯定會殺死它。

相關問題