gpt4 book ai didi

c# - 在多线程观察者模式中使用什么集合?

转载 作者:行者123 更新时间:2023-11-30 15:28:53 25 4
gpt4 key购买 nike

我目前正在实现观察者设计情境。

我在主类(class)有我的注册观察员名单。

private static volatile List<IObserver> registeredObservers;

每个观察者都是一个网络套接字,当套接字已连接并且一切正常时,它会向可观察类注册自己。如果出现错误或套接字只是断开连接,则从可观察对象中注销/删除其自身。

这一切似乎都运作良好。我很高兴。

但现在在我的主类中,我循环遍历所有已注册的观察者,如下所示:

private void SendEventToObservers(ILogItem item)
{
foreach (var observer in registeredObservers)
{
if (observer != null)
{
observer.OnMessageRecieveEvent(new ObserverEvent(item));
}
}
}

然后会抛出以下错误:

Collection was modified; enumeration operation may not execute

现在我在另一个 SO 线程中读到我需要为每个更改以添加 .ToList() :

foreach (var observer in registeredObservers.ToList()) 

现在这并没有完全解决我的问题,因为如果观察者在忙于循环时从列表中删除它自己,那么 .toList() 会创建列表的“旧”表示吗?

我在想会不会有一种更好的并发列表,它可以在访问时以及添加和删除观察者时阻塞?

或者当前的 .ToList() 解决方案是否有效?

最佳答案

既然您已经提到可以在访问时以及添加和删除观察者时进行阻塞,我认为同步线程是最安全的选择。

如果您没有运行耗时的操作,这将是最佳解决方案。只需锁定列表并执行操作:

添加:

lock (registeredObservers)
registeredObservers.Add(newObserver);

删除:

lock (registeredObservers)
registeredObservers.Remove(outOfServiceObserver);

迭代:

lock (registeredObservers)
foreach (var observer in registeredObservers)
{
if (observer != null)
{
observer.OnMessageRecieveEvent(new ObserverEvent(item));
}
}

更新:

@fourpastmidnight 提出了这个解决方案的一个严重问题,我认为最好将答案编辑为更安全的东西:遍历列表的副本

lock (registeredObservers)
foreach (var observer in registeredObservers.ToArray())
{
if (observer != null)
{
observer.OnMessageRecieveEvent(new ObserverEvent(item));
}
}

关于c# - 在多线程观察者模式中使用什么集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24796311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com