SignalR加入/离开组无法正常工作

时间:2014-02-14 11:34:19

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

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

My 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);
    }

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

        $(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);
        });

广播方法转到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;
    }

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

1 个答案:

答案 0 :(得分:4)

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

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