C# SignalR LongPolling多个组。针对单个客户端异常添加
这件事我已经挣扎了一段时间了。我们正在使用最新的信号器2.0.3。当我们添加到多个信号器组时,就会出现问题。只有当多个添加发生在具有不同组名的同一connectionId中时,才会引发异常。仅当选择了LongPolling传输时才会引发异常。只有在添加到6个以上的唯一组名(5个或更少)时才会引发异常,并且可以正常工作 下面是一个简化的示例: Index.cshtml:C# SignalR LongPolling多个组。针对单个客户端异常添加,c#,javascript,signalr,C#,Javascript,Signalr,这件事我已经挣扎了一段时间了。我们正在使用最新的信号器2.0.3。当我们添加到多个信号器组时,就会出现问题。只有当多个添加发生在具有不同组名的同一connectionId中时,才会引发异常。仅当选择了LongPolling传输时才会引发异常。只有在添加到6个以上的唯一组名(5个或更少)时才会引发异常,并且可以正常工作 下面是一个简化的示例: Index.cshtml: @model Int32? <!DOCTYPE html> <head>
@model Int32?
<!DOCTYPE html>
<head>
<title></title>
<script src="@Url.Content("~/Scripts/jquery.min.js")" type="text/javascript"/>
<script src="@Url.Content("~/Scripts/jquery.signalR-2.0.3.min.js")"
type="text/javascript" />
<script src="@Url.Content("~/signalr/hubs")" type="text/javascript"/>
</head>
<script>
_testHub = $.connection.testHub;
_testHub.client.sayHello = sayHello;
$.connection.hub.start({ transport: 'longPolling' })
.done(function() {
addAllGroups();
});
function sayHello(aMessage, aGroupName) {
console.info("GroupName: " + aGroupName
+ " Message Sent:" + aMessage);
};
function addAllGroups() {
for (var i = 0;
i < @(Model.HasValue ? Model.Value : 1 ); i++) {
addToGroupAndBroadcast(i);
}
};
function addToGroupAndBroadcast(aGroupName) {
_testHub.server.addToGroupAndBroadcast(aGroupName)
.fail(function (desc) {
console.info("Error: " + desc);
});
};
</script>
TestHub.cs:
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace Instrumar.ProductionDashboard.Hubs
{
public class TestHub : Hub
{
#region Public Members
public void AddToGroupAndBroadcast(string aGroupName)
{
GlobalHost.ConnectionManager.GetHubContext<TestHub>().Groups.Add(Context.ConnectionId, aGroupName).Wait();
Clients.Group(aGroupName).sayHello("Hello", aGroupName);
}
#endregion
}
}
控制器接受一个整数作为输入,该整数是要执行的加法数。例如,如果您呼叫:
一组。添加效果很好
两组。添加效果良好
三组。添加效果良好
四组。添加效果良好
五组。添加效果良好
六组。添加断开的
七组。添加断开的
八组。添加断开的
九组。添加断开的
十组。添加断开的
当我说break时,我在TestHub.cs中得到一个“System.Threading.Tasks.TaskCanceledException”,它在等待任务完成的队列中。ServerSentEvents的所有功能都很好,但在很长一段时间内,问题仍然存在。我做错了什么?我可以拥有不超过5个长轮询的信号器组吗?救救我!:)
更新:在客户端调用之间使用setTimeout进行1毫秒睡眠修复了该问题。这似乎可以减少“网络”选项卡中挂起的连接数。当您达到单浏览器连接限制时,添加到组的能力可能会发生一些变化。如果能确切地知道为什么这样做不起作用,那就太好了。看起来这里有一个相关的问题已经解决了。如果是这样的话,您必须提取代码并重新编译自己的DLL。此外,您的错误也可能是由超时引起的 这也可能与您的问题有关: 。。。因为您正在尝试创建的连接id 删除可能不再可用。那么,, TaskCanceledException在请求超时后抛出
参考您可以有5个以上具有长轮询的组,但您必须通过不在循环中添加组来解决连接问题 从
Groups.Add返回的任务只有在从消息总线接收到一条ACK消息时才完成,该消息指示客户端的消息(通知其组添加)已发送。
如果来自客户端的addToGroupAndBroadcast
调用绑定了超过5个(或浏览器强制执行的任何数字)的未决AJAX请求,则无法向客户端发送消息。如果将已完成回调附加到客户端调用:
_testHub.server.addToGroupAndBroadcast(groupName).done(function() {
console.log("complete");
});
您将看到第一个调用几乎立即完成
这是第一个Groups.Add调用返回的时间。发送给sayHello
的消息不再被发送,因为它需要另一个打开的轮询请求,客户端正在创建该请求,但不会得到处理,因为来自客户端的多个其他挂起请求已首先进入队列(这些请求都在等待addToGroupAndBroadcast
完成)
因此,在第一次调用Groups.Add之后,服务器无法向客户端发送任何内容,MessageHub无法发送其ACK,这将解析剩余的组。Add
承诺。
因此,由于超时,这些任务会抛出TaskCanceledException
作为一种解决方法,我建议创建一个接受组名数组的hub方法:
public async Task AddToGroups(string[] names)
{
foreach (var name in names)
{
await Groups.Add(Context.ConnectionId, name);
Clients.Group(name).sayHello("Hello", name);
}
}
首先,我没有看到你的VS版本和为什么你不能升级到最新版本的开源SignalR之间的联系。其次,当我实现SignalR时,我不需要您发布的任何代码。你从哪里得到你正在使用的代码的?是你自己写的吗?谷歌搜索给我的印象是大于1.2.1的signar版本需要.NET4.5,而VisualStudio2010不支持这一点。一个人提到你们可以自己从源代码中重建信号器,但我们认为那个选项是有风险的。是的,那个代码是我自己写的。这个js文件最初要简单得多。我们一直遵循微软的信号器指南,但当我们将软件发布到野外时,我们遇到了一些问题。由于现实世界的特殊情况,必须对其进行修改。我们的软件在一个网站上运行,该网站在一个内部网络上全天候显示,每秒有数百次信号更新。其中一些问题可能是由于我们使用的旧版本的Signal(最初是1.0.1)造成的,我们可能已经修复了最新版本的Signal中不再存在的bug。此外,上面JS文件中的一些代码是特定于应用程序的。我试图将JS文件缩减到最小,并保留与此问题相关的所有内容。您可能应该发布更多与服务.ClientServices.Registration.Register
方法相关的代码,以及将哪些运行时值传递给DashboardHub.Register(String aToken)
。您可以主动调试并查看异常,还是只是将其记录到一个文件中?看起来这里有一个相关的问题已经解决了。如果是这样的话,你将不得不提取代码并重新编译你自己的DLL。看起来这可能是相关的。我们今天刚刚收到VS 2013,所以我正在使用最新版本的SignalR针对.net 4.5构建项目,如果错误得到修复,赏金归你。祝你好运。如果可能的话,我会尽量避免使用异步方法,例如.Wait()
,不幸的是,最新版本的SignalR 2.0.3和.net 4.5仍然可以重现该问题。因此,它必须与您的特定代码相关。关于删除.Wait()
有什么想法吗?我没有这样的经历
_testHub.server.addToGroupAndBroadcast(groupName).done(function() {
console.log("complete");
});
public async Task AddToGroups(string[] names)
{
foreach (var name in names)
{
await Groups.Add(Context.ConnectionId, name);
Clients.Group(name).sayHello("Hello", name);
}
}