【发布时间】:2018-03-15 04:42:21
【问题描述】:
我正在强调我正在编写的服务,它使用取自 AcceptWebSocketAsync 的 WebSocket。我用来通过 WebSocket 发送消息的代码是这样的:
static bool
SendMessage(WebSocket webSocket, WebSocketMessage message, byte[] buffer, CancellationToken cancellationToken)
{
try {
var endOfMessage = false;
do {
using(var timeout = new CancellationTokenSource(webSocketsTimeout))
using(var lcts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token)) {
var count = message.Content.Read(buffer, 0, buffer.Length);
endOfMessage = count < buffer.Length;
// ReSharper disable once MethodSupportsCancellation
webSocket
.SendAsync(new ArraySegment<byte>(buffer, 0, count), message.Type, endOfMessage, lcts.Token)
.Wait() // SendAsync should be canceled using the Token.
;
}
} while(endOfMessage == false);
return true;
}
catch(Exception e) {
TraceConnectionError(e);
return false;
}
finally {
message.Dispose();
}
}
我的问题是在“压力”下(我每 30 秒打开和关闭 6 个连接,直到系统出现故障),我得到:
Unhandled Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.Net.HttpListenerException: An operation was attempted on a nonexistent network connection
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs)
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.<MultipleWriteAsyncCore>d__38.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendFrameAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.Net.WebSockets.WebSocketBase.WebSocketOperation.<Process>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendAsyncCore>d__47.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
我使用的Wait() 不应该足以“观察”任务异常吗?
【问题讨论】:
-
没有。 “using”语句有自己的异常处理程序。删除 using 语句。
-
我不明白你的意思。 using 没有处理任何事情,异常在 SendAsync() 上引发,并且应该在 Wait() 上“观察到”...如果我删除 using 我只会得到泄漏(至少在 LinkedTokenSource 上) ...我错过了什么?
-
using 语句的内部是一个内置的异常处理程序。
-
我理解 using 翻译成什么(基本上是 try..finally 与最后的处置)。该翻译如何解释我所看到的行为?
-
异常表示:在不存在的网络连接上尝试了操作。可能是之前的“使用”超时,您没有测试连接是否关闭或为空。
标签: c# exception websocket task cancellation