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