Ada*_*dam 9 javascript c# signalr
我一直在努力解决这个问题.我们正在使用最新的SignalR 2.0.3.当我们添加到多个SignalR组时会发生问题.仅当具有不同组名的同一connectionId发生多个添加时,才会抛出异常.仅在选择LongPolling传输时才会抛出异常.只有当您添加6个或更少的5个以上的唯一组名时才会抛出异常,并且它可以正常工作.
这是一个简化的例子:
Index.cshtml:
@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>
Run Code Online (Sandbox Code Playgroud)
SignalRTestController.cs:
using System;
using System.Web.Mvc;
namespace Instrumar.ProductionDashboard.Controllers
{
public class SignalRTestController : Controller
{
#region Public Members
public ActionResult Index()
{
return View((int?)Convert.ToInt32(Request.Url.Segments[4]));
}
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
Startup.cs:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var lHubConfiguration = new HubConfiguration {EnableDetailedErrors = true};
app.UseErrorPage();
app.MapSignalR(lHubConfiguration);
}
}
}
Run Code Online (Sandbox Code Playgroud)
控制器采用整数作为输入,这是要执行的Add的数量.例如,如果您致电:
http://yourip.com/WebApplicationName/SignalRTest/Index/1一个Groups.Add 工作正常 http://yourip.com/WebApplicationName/SignalRTest/Index/2两个Groups.Add 工作正常 http://yourip.com/ WebApplicationName/SignalRTest/Index/3三个Groups.Add 工作正常 http://yourip.com/WebApplicationName/SignalRTest/Index/4四个Groups.Add 工作正常 http://yourip.com/WebApplicationName/SignalRTest/Index/5五Groups.Add 工作得很好 http://yourip.com/WebApplicationName/SignalRTest/Index/6六个Groups.Add 破了 http://yourip.com/WebApplicationName/SignalRTest/Index/7七个Groups.Add 破解 http:// yourip .com/WebApplicationName/SignalRTest/Index/8八个Groups.Add 破了 http://yourip.com/WebApplicationName/SignalRTest/Index/9九个Groups.Add 破了 http://yourip.com/WebApplicationName/SignalRTest/Index/10十个Groups.Add 破碎
...
当我说破坏时,我在TestHub.cs中找到等待任务完成的行中的"System.Threading.Tasks.TaskCanceledException".ServerSentEvents一切正常,但对于LongPolling,问题依然存在.我究竟做错了什么?使用LongPolling,我不能拥有超过5个SignalR组吗?帮我!:)
更新:在客户端调用之间使用setTimeout进行1毫秒的休眠可以解决问题.这似乎减轻了网络选项卡中待处理连接的数量.当达到单个浏览器连接限制时,可能会出现添加到组的能力.很高兴知道为什么这不起作用.
您可以拥有超过 5 个具有长轮询的组,但您必须通过不循环添加到组来解决连接问题。
Groups.Add仅当从消息总线接收到指示客户端的消息(通知其组添加)已发送的 ACK 消息时,返回的任务才完成。如果有超过 5 个(或浏览器强制执行的任何数量)与addToGroupAndBroadcast客户端调用相关的挂起 AJAX 请求,则无法将消息发送到客户端。如果您将完成回调附加到您的客户端调用:
_testHub.server.addToGroupAndBroadcast(groupName).done(function() {
console.log("complete");
});
Run Code Online (Sandbox Code Playgroud)
您会看到第一个调用几乎立即完成。
这是第一个 Groups.Add 调用返回的时间。消息sayHello不再发送,因为它需要另一个开放的轮询请求,客户端正在创建该请求,但不会得到处理,因为有多个来自客户端的其他待处理请求已首先排队(这些都是)等待addToGroupAndBroadcast完成)。
因此,在第一次调用 Groups.Add 后,服务器无法向客户端发送任何内容,MessageHub 无法发送其 ACK 来解决剩余的Groups.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);
}
}
Run Code Online (Sandbox Code Playgroud)