我正在使用SignalR通知客户一些变化。 我的中心(但知道它是一个SignalR中心并不是根本)定义为
public class NotificationHub : Hub
{
private static readonly IHubContext HubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
private static readonly IDictionary<int, string> UserConnectionMapping = new Dictionary<int, string>();
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private const string UserId = "UserId";
private readonly object userConnectionMappingLock = new object();
public static void Static_UpdateStatus(int userId, string message)
{
lock(userConnectionMappingLock ) //This causes troubles
{
if (UserConnectionMapping.ContainsKey(userId))
{
var connectionId = UserConnectionMapping[userId];
HubContext.Clients.Client(connectionId).updateNotifications(message);
}
}
}
public override Task OnConnected()
{
if (Context.QueryString[UserId] == null) return base.OnConnected();
var userId = int.Parse(Context.QueryString[UserId]);
Log.Debug($"User {userId} connected on SignalR with Connection Id {Context.ConnectionId}");
lock (userConnectionMappingLock)
{
UserConnectionMapping[userId] = Context.ConnectionId;
}
return base.OnConnected();
}
因为它是静态的方法(并且因为我需要从外部类访问所以不能这样),我是否应该声明锁定静态?考虑一下只有一个NotifyHub实例。感谢
答案 0 :(得分:1)
你锁定的东西和被保护的东西应该具有相同的寿命和范围;目前UserConnectionMapping
为static
,而userConnectionMappingLock
是每个实例,这是灾难的处方。
坦率地说,static
词典总是有点危险,但可以安全使用;选项:
userConnectionMappingLock
符合字典的范围 - 将static
添加到userConnectionMappingLock
(或从static
删除UserConnectionMapping
,请参阅3)userConnectionMappingLock
(只是扔掉它),并在字典本身上lock
(UserConnectionMapping
)UserConnectionMapping
不成为static
- 因此每个中心实例都有一个字典(假设NotificationHub
的生命周期适用于此)ConcurrentDictrionary<int,string>
我可能会倾向于最后一个 - 你不太可能用它来射击你的脚。虽然我认为可以在1/2 / 4中使用3 以及中的任何一个。