C# SignalR LongPolling多个组。针对单个客户端异常添加

C# SignalR LongPolling多个组。针对单个客户端异常添加,c#,javascript,signalr,C#,Javascript,Signalr,这件事我已经挣扎了一段时间了。我们正在使用最新的信号器2.0.3。当我们添加到多个信号器组时,就会出现问题。只有当多个添加发生在具有不同组名的同一connectionId中时,才会引发异常。仅当选择了LongPolling传输时才会引发异常。只有在添加到6个以上的唯一组名(5个或更少)时才会引发异常,并且可以正常工作 下面是一个简化的示例: Index.cshtml: @model Int32? <!DOCTYPE html> <head>

这件事我已经挣扎了一段时间了。我们正在使用最新的信号器2.0.3。当我们添加到多个信号器组时,就会出现问题。只有当多个添加发生在具有不同组名的同一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>
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);
    }
}