System.ObjectDisposedException 在 WebSocket 通信上抛出
System.ObjectDisposedException throwed on WebSocket communication
我正在尝试使用 WebSockets 在 Web 浏览器客户端和 ASP.NET 服务器之间进行通信。
我提出了一组不同大小的请求,每个请求之间有几秒钟的时间间隔。前三个正确通过,但一个精确的,另一个没有任何特别之处,关闭 WebSocket 连接,在服务器端抛出异常。
此异常的错误消息和堆栈跟踪如下所示:
FATAL ERROR: Cannot access a disposed object.
Object name: 'System.Web.WebSockets.AspNetWebSocket'.
at System.Web.WebSockets.AspNetWebSocket.ThrowIfDisposed()
at System.Web.WebSockets.AspNetWebSocket.SendAsyncImpl(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken, Boolean performValidation)
at System.Web.WebSockets.AspNetWebSocket.SendAsync(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken)
at [my code path here...]
这可能是线程问题,因为我在与 websockets 通信的函数中到处都使用 async
方法。
我知道此代码(在 socket.SendAsync
)抛出了异常:
public class SocketTranslater
{
private WebSocket socket;
private JavaScriptSerializer serializer;
// [...]
private ArraySegment<byte> Encode(Object data)
{
string json = serializer.Serialize(data);
return (new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)));
}
public async Task Send(Object packet)
{
ArraySegment<byte> encoded = this.Encode(packet);
await socket.SendAsync(encoded, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
套接字是从另一个创建的 class :
public class EventSender : IHttpHandler
{
private static List<SocketTranslater> socketTranslaters = new List<SocketTranslater>();
public void ProcessRequest(HttpContext context)
{
this.id = context.Request.UserHostName + ":" + context.Request.UserAgent;
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(ProcessSocket);
}
}
private async Task ManageSocket(AspNetWebSocketContext context)
{
WebSocket socket = context.WebSocket;
SocketTranslater translater = new SocketTranslater(socket);
translaters.add(translater);
while (true)
{
// Manage messages, using the other class to send responses.
translater.Send(/* Any struct here */);
}
}
无奈,我的项目太大,没法把所有的代码放在这里。
是否知道错误来源或您需要的其他信息?
更新:
经过多次测试,我没有时不时出现这个异常。我总是做同样的事情,但服务器似乎有随机行为。
这让我的问题更加奇怪...
最后,经过更多的测试和有趣的问题和来自这里的回答(比如this one),我明白了:
我的问题是我将 WebSockets 存储在与主机名链接的字典中。因此,在我的服务器上首次连接客户端时,一切正常。但是如果我刷新页面,websocket 被服务器关闭(因为没有机会再次使用它)并且创建了另一个。
但是由于我对两个套接字(已弃用的套接字和新的套接字)使用了相同的密钥,我试图用以前的套接字回答新客户端,该套接字已关闭。 (处置 = ASP.NET 关闭)。
所以我唯一要做的就是在客户端断开连接时(在 ManageSocket
结束时)从列表中删除一个套接字。并禁止客户端使用相同的主机名连接两次。
我没有提到我将套接字与主机名链接的部分,所以我承认你帮不了我...我很抱歉。
我正在尝试使用 WebSockets 在 Web 浏览器客户端和 ASP.NET 服务器之间进行通信。
我提出了一组不同大小的请求,每个请求之间有几秒钟的时间间隔。前三个正确通过,但一个精确的,另一个没有任何特别之处,关闭 WebSocket 连接,在服务器端抛出异常。
此异常的错误消息和堆栈跟踪如下所示:
FATAL ERROR: Cannot access a disposed object.
Object name: 'System.Web.WebSockets.AspNetWebSocket'.
at System.Web.WebSockets.AspNetWebSocket.ThrowIfDisposed()
at System.Web.WebSockets.AspNetWebSocket.SendAsyncImpl(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken, Boolean performValidation)
at System.Web.WebSockets.AspNetWebSocket.SendAsync(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken)
at [my code path here...]
这可能是线程问题,因为我在与 websockets 通信的函数中到处都使用 async
方法。
我知道此代码(在 socket.SendAsync
)抛出了异常:
public class SocketTranslater
{
private WebSocket socket;
private JavaScriptSerializer serializer;
// [...]
private ArraySegment<byte> Encode(Object data)
{
string json = serializer.Serialize(data);
return (new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)));
}
public async Task Send(Object packet)
{
ArraySegment<byte> encoded = this.Encode(packet);
await socket.SendAsync(encoded, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
套接字是从另一个创建的 class :
public class EventSender : IHttpHandler
{
private static List<SocketTranslater> socketTranslaters = new List<SocketTranslater>();
public void ProcessRequest(HttpContext context)
{
this.id = context.Request.UserHostName + ":" + context.Request.UserAgent;
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(ProcessSocket);
}
}
private async Task ManageSocket(AspNetWebSocketContext context)
{
WebSocket socket = context.WebSocket;
SocketTranslater translater = new SocketTranslater(socket);
translaters.add(translater);
while (true)
{
// Manage messages, using the other class to send responses.
translater.Send(/* Any struct here */);
}
}
无奈,我的项目太大,没法把所有的代码放在这里。
是否知道错误来源或您需要的其他信息?
更新:
经过多次测试,我没有时不时出现这个异常。我总是做同样的事情,但服务器似乎有随机行为。
这让我的问题更加奇怪...
最后,经过更多的测试和有趣的问题和来自这里的回答(比如this one),我明白了:
我的问题是我将 WebSockets 存储在与主机名链接的字典中。因此,在我的服务器上首次连接客户端时,一切正常。但是如果我刷新页面,websocket 被服务器关闭(因为没有机会再次使用它)并且创建了另一个。
但是由于我对两个套接字(已弃用的套接字和新的套接字)使用了相同的密钥,我试图用以前的套接字回答新客户端,该套接字已关闭。 (处置 = ASP.NET 关闭)。
所以我唯一要做的就是在客户端断开连接时(在 ManageSocket
结束时)从列表中删除一个套接字。并禁止客户端使用相同的主机名连接两次。
我没有提到我将套接字与主机名链接的部分,所以我承认你帮不了我...我很抱歉。