2017-03-14 17 views
0

を使用するSystem.Net.WebSockets.WebSocket私は1つのスレッドで読み取りループを持っています。WebSocket Threadsafeを閉じる

var result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); 

他のスレッドから書きます。

lock (ws) 
    ws.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None).Wait(); 

これは問題なく動作します。

私の質問は、この接続をきれいに閉じることができますか?例外結果を閉じる

任意の試み:

await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye", CancellationToken.None); 
InvalidOperationException: 'Concurrent reads are not supported.' 

は、私は受信ループ内からws.CloseAsyncを呼び出すことができるようにws.ReceiveAsyncCancellationTokenを通過しようとしました。それはReceiveAsyncコールを中断せず、次のメッセージが到着したときに戻った。

読み取りループ外のソケットをきれいに閉じることは可能ですか? WebSocketプロトコルでクローズメッセージを送信するというコンセプトがある場合は、「接続を閉じる」というメッセージを実装できますが、それは過剰なようです。

+0

'CancellationToken'は' ReceiveAsync'をキャンセルしませんか?それは非常に奇妙なようです。 –

+0

@StephenCleary少なくとも次のメッセージが届くまでに5〜10秒後に届きます – hultqvist

+1

その場合は、 'CloseOutputAsync'を呼び出し、' CloseSent'メッセージタイプを読み込みで処理する必要があります。 –

答えて

0

、あなたはCloseOutputAsyncを呼び出して、あなたの読み込み中 CloseSentメッセージタイプを処理する必要があります。 - 別のスレッドがReceiveAsync上で待っている間午後1時49分

でステファン・クリアリー3月14日あなたはCloseOutputAsyncを呼び出すことができます。

1

このコードでは、同時読み取りは表示されません。ReceiveAsyncを1つのスレッドからのみ呼び出す場合、次のスレッドを開始する前に操作の結果を待っている場合は、この例外は発生しません。それはどこに投げられるのですか?

書き込み部分のご提案:ロックとブロッキング書き込み(.Wait())を使用すると、あなたが望むものではない可能性があるフルスレッド(他のハンドルを実行する可能性があります)をブロックしています。

await semaphore.WaitAsync(); 
try 
{ 
    await ws.SendAsync(); 
} 
finally 
{ 
    semaphore.Release(); 
} 

をエラーメッセージのテキストが正確ではない、それは実際にCloseコールを保護するためにも、同時SendClose、あなたが使用することができ、同じセマフォ言っている場合:あなたが行うことができ、より良い使用SemaphoreSlim代わりに、 :

その場合
await semaphore.WaitAsync(); 
try 
{ 
    await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye", CancellationToken.None); 
} 
finally 
{ 
    semaphore.Release(); 
} 
+0

'CloseAsync'コールで例外がスローされます。 – hultqvist

関連する問題