public override Task SendGroupAsync(string groupName, string methodName, object[] args) { if (groupName == null) { throw new ArgumentNullException(nameof(groupName)); } var group = _groups[groupName]; if (group != null) { // Can't optimize for sending to a single connection in a group because // group might be modified inbetween checking and sending List <Task> tasks = null; SerializedHubMessage message = null; SendToGroupConnections(methodName, args, group, null, ref tasks, ref message); if (tasks != null) { return(Task.WhenAll(tasks)); } } return(Task.CompletedTask); }
public override Task SendGroupsAsync(IReadOnlyList <string> groupNames, string methodName, object[] args) { // Each task represents the list of tasks for each of the writes within a group List <Task> tasks = null; SerializedHubMessage message = null; foreach (var groupName in groupNames) { if (string.IsNullOrEmpty(groupName)) { throw new InvalidOperationException("Cannot send to an empty group name."); } var group = _groups[groupName]; if (group != null) { SendToGroupConnections(methodName, args, group, null, ref tasks, ref message); } } if (tasks != null) { return(Task.WhenAll(tasks)); } return(Task.CompletedTask); }
// Tasks and message are passed by ref so they can be lazily created inside the method post-filtering, // while still being re-usable when sending to multiple groups private void SendToGroupConnections(string methodName, object[] args, ConcurrentDictionary <string, HubConnectionContext> connections, Func <HubConnectionContext, bool> include, ref List <Task> tasks, ref SerializedHubMessage message, CancellationToken cancellationToken) { // foreach over ConcurrentDictionary avoids allocating an enumerator foreach (var connection in connections) { if (include != null && !include(connection.Value)) { continue; } if (message == null) { message = CreateSerializedInvocationMessage(methodName, args); } var task = connection.Value.WriteAsync(message, cancellationToken); if (!task.IsCompletedSuccessfully) { if (tasks == null) { tasks = new List <Task>(); } tasks.Add(task.AsTask()); } } }
private Task SendToAllConnections(string methodName, object[] args, Func <HubConnectionContext, bool> include) { List <Task> tasks = null; SerializedHubMessage message = null; // foreach over HubConnectionStore avoids allocating an enumerator foreach (var connection in _connections) { if (include != null && !include(connection)) { continue; } if (message == null) { message = CreateSerializedInvocationMessage(methodName, args); } var task = connection.WriteAsync(message); if (!task.IsCompletedSuccessfully) { if (tasks == null) { tasks = new List <Task>(); } tasks.Add(task.AsTask()); } } if (tasks == null) { return(Task.CompletedTask); } // Some connections are slow return(Task.WhenAll(tasks)); }
public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList <string> excludedIds) { if (groupName == null) { throw new ArgumentNullException(nameof(groupName)); } var group = _groups[groupName]; if (group != null) { List <Task> tasks = null; SerializedHubMessage message = null; SendToGroupConnections(methodName, args, group, connection => !excludedIds.Contains(connection.ConnectionId), ref tasks, ref message); if (tasks != null) { return(Task.WhenAll(tasks)); } } return(Task.CompletedTask); }