2012-07-29 13 views
17

これは私が先週調査したところでは解決策が見つからない問題です。同じことを尋ねる投稿を見つけましたが、決して答えを得ることはできません。WCFサービスからのストリームを読み込まずにストリームを中止する方法はありますか?

私はWCFサービスを持っていて、その中にstreamを含むオブジェクトを返します。私はbasicHttpBindingをストリーム転送とMtomを使ってクライアントに送ります。

クライアントはWCFサービスを呼び出し、応答オブジェクトを受信した直後にプロキシを閉じます。

次に、クライアントはWCFサービスから取得したストリームを読み取り、ローカルディスク上のファイルに書き込みます。これらはすべて正常に動作します。

私の問題は、クライアントが操作を中止し、WCFサービスからのデータのダウンロードを停止したいときです。 .close()をストリームに呼び出すと、serverReply.DataStream.Close();などのストリームがブロックされ、WCFサービスからストリーム全体が読み込まれて終了するまで続きます。ストリームはかなり大きく、ネットワークは常に高速であるとは限りません。

これは、ネットワークリソースの使用には非常に好ましくありません。これは、基本的には使用されていないデータで無駄になります。 basicHttpBindingは、WCFサービスサーバーに対して2つの同時TCP接続(デフォルト)を許可するだけなので、ストリームが最後まで読み込まれるまで、他の接続の試行をブロックします。

私は同時接続数を増やすことができますが、これはトラブルの原因となるため、問題の解決策になります。

たとえば、20件のダウンロードが中断されたデータをダウンロードしているとします。私は転送を完全に停止させる必要があります。

クライアントでは、ストリームオブジェクトは普通のStreamクラスなので、closeメソッドのみがあり、それ以外は何もありません。

.close()または.abort()をプロキシオブジェクトにコールすると、.dispose()または他の方法を使用しても破棄されません。 サーバー側ではOperationContext.OperationCompletedイベントを処理しますが、streamのデータが最後まで読み込まれるまでは起動されません。

それで、ストリームを完全に読み込まずにストリームを閉じたり、中止したりするにはどうすればいいですか?

+0

これで運がいいですか? – Schultz9999

+0

本当に大きなファイルを送信しているときに同じ問題が発生しました...本当に明白な何かが欠落している必要があります。回避策としてチャンクを実装する必要があります。 –

答えて

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> 

私はタイムアウトANFバッファの長さを最小限に抑え、中止または近いと何が起こるか見てみます。

+1

私はそれを試みたが、それは助けにはならない。サーバーがストリームの送信を開始すると、ストリームはすべてがクライアントによって受信されるまで停止しません。プロキシを閉じることは何もしません。 コミュニケーションを止める方法はないようです。 クライアントがストリームの読み込みを停止すると、tcpウィンドウゼロがサーバーに戻るのがわかります。そして、サーバは、クライアントが再び読む準備ができているかどうかを調べるために、窓ゼロプローブを定期的に送信する。もちろん、クライアントはウィンドウゼロを再び送り返します。 これはプロセスが終了するまで永遠に続きます。 – Yev

+0

HttpClientクラスを使用してストリームを読み込もうとしましたが、ストリームを閉じることができましたか? –

+0

WCFサービスを呼び出さずにどうすればいいですか? 私はもう少し研究を重ねてきましたが、クライアント側からストリームを閉じる方法はないようです。 私は別のアプローチを試みました。私は別のサービス、コントロールサービスを作成し、そこからストリームを閉じることを試みました(サーバー側)。しかし、運がない。何かがうまくいかず、閉じたり、処分したりしません。 – Yev

1

調査の結果、WCFクライアントはcloseTimeoutがellapseになるまでストリームからの読み取りを継続していることが判明した後、接続を中断します。問題を最小限に抑えるために、クライアントのcloseTimeoutを減らすことができます。

注:ストリームを処理するコードをtry/catchブロックにラップする必要があります。 stream.Dispose()メソッドは、not throwing exceptions in Dispose methodのガイドラインを制動するTimeoutExceptionをスローします。

0

私はあなたがクローズの後に単にバッファを受け取っていると思います。 maxBufferSizeをより低い値に設定する必要があります。

ストリームをラップして読み込みを無効にすることで、サーバー上の読み込みデータ量を制限することもできます。低帯域幅のクライアントを使用している場合は、より小さなチャンクを使用し、実際に読み取った量と一致するように、読み取りメソッドから対応するカウントを返します。これは、バッファの充填率を制限します。

この件に関する私自身のテストでは、NeverEndingStreamの作成とデータの返却が常に必要でした。ある時点で私はクライアント上でクローズと呼ばれ、すぐにクローズがサーバー上で呼び出されました。これは、バッファーが単に空になったことを示しています。なぜなら、最後までストリームを読み取ることができないからです。

問題が解決しない場合は、オーバーライドされたストリームのReadメソッドのタイミングを追跡することをお勧めします。 currentReadtime - lastReadTimeが> xの場合、代わりにCloseを呼び出して例外をスローする可能性があります。それは確かにそれを殺すでしょう。

関連する問題