【问题标题】:SignalR join/leave group doesn't work correctlySignalR 加入/离开组无法正常工作
【发布时间】:2014-03-13 18:02:23
【问题描述】:

我有一个使用 SignalR 的简单应用程序,我不想为不同的机器显示不同的数据,这取决于用户选择了哪台机器

我的 Hub 类如下所示:

    readonly ISprayBroadcaster _sprayBroadcaster;
    readonly IWorkRecordRepository _workRecordRepository;

    public SprayHub(ISprayBroadcaster sprayBroadcaster, IWorkRecordRepository workRecordRepository)
    {
        _sprayBroadcaster = sprayBroadcaster;
        _workRecordRepository = workRecordRepository;
    }

    public void Broadcast(string name)
    {
        Process.DataProcess(_workRecordRepository, Clients, name).Wait();
    }

    public void SwapGroup(string previousGroup, string newGroup)
    {
        Groups.Remove(Context.ConnectionId, previousGroup);
        Groups.Add(Context.ConnectionId, newGroup);
    }

    public void JoinGroup(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName);
    }

这是我在客户端初始化集线器并在其上调用广播方法的方式:

        $(function () {
            hub = $.connection.sprayHub;
            function init() {
                hub.server.joinGroup("machine1");
                hub.server.broadcast("machine1");
            };

            // Client-side hub method that the server will call
            hub.client.updateData = function (shifts) {
                ViewModel.Measurements(recreateArray(shifts));
            }
            $.connection.hub.start().done(init);
        });

Broadcast 方法转到 DataProcess 方法,该方法将数据从分配的组中填充到客户端:

    public static async Task DataProcess(IWorkRecordRepository workRecordRepository, IHubConnectionContext hubClients, string machine)
    {
        var shiftRecords = await workRecordRepository.Records(machine, DateTime.Now).ToList();
        var result = SLGT.Sentinel.Core.Calculations.Shifts(shiftRecords);
        hubClients.Group(machine).updateData(result);
    }

同时,我设置了一个广播器,它在循环中运行并为客户端提供适当的数据。这是来自广播者的广播方法,它调用相同的 DataProcess 方法来为系统中找到的每台机器填充数据:

    void Broadcast(object state)
    {
        lock (_updateLock)
        {
            if (_updating) 
                return;

            _updating = true;

            var machines = _workRecordRepository.Machines();
            machines.Subscribe(async machine =>
            {
                await Process.DataProcess(_workRecordRepository, Clients, machine);
            });

            _updating = false;
        }
    }

最后,当用户在客户端单击不同机器的按钮时,我将组交换为要为该客户端显示的适当数据:

    $(".machineButton").click(function () {
        var name = $(this).attr("id");
        hub.server.swapGroup(previousGroup, name);
        previousGroup = name;
    }

现在,当我在测试环境中运行此应用程序时,一切正常。当我在服务器上运行它时,组之间的交换无法正常工作,并且客户端不断地收到相同的数据集。为什么会发生?正如我所说的本地版本工作正常,所以我不知道如何调试它?

【问题讨论】:

    标签: javascript asp.net asynchronous signalr asp.net-mvc-5


    【解决方案1】:

    组管理方法(添加和删除)是异步的。如果您不等待返回的任务,则在出现竞争条件后立即发送到组,这样您刚刚添加的客户端可能不会收到该消息。此外,您永远不应该在集线器方法中调用 .Wait() 。使中心方法异步并等待它。

    readonly ISprayBroadcaster _sprayBroadcaster;
    readonly IWorkRecordRepository _workRecordRepository;
    
    public SprayHub(ISprayBroadcaster sprayBroadcaster, IWorkRecordRepository workRecordRepository)
    {
        _sprayBroadcaster = sprayBroadcaster;
        _workRecordRepository = workRecordRepository;
    }
    
    public async Task Broadcast(string name)
    {
        await Process.DataProcess(_workRecordRepository, Clients, name);
    }
    
    public async Task SwapGroup(string previousGroup, string newGroup)
    {
        await Groups.Remove(Context.ConnectionId, previousGroup);
        await Groups.Add(Context.ConnectionId, newGroup);
    }
    
    public async Task JoinGroup(string groupName)
    {
        await Groups.Add(Context.ConnectionId, groupName);
    }
    

    另外,您的生产环境是单个 Web 服务器还是负载平衡的服务器场?如果是农场,你需要configure SignalR scale-out

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-08
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多