我现在有一个事件处理器类,它有一个Dictionary来存储所有订阅。实际上它是一本字典词典。此进程类与第三方远程服务器通信以发出对目标数据的请求。我问这个问题,因为现在我们正在经历一些偶尔订阅丢失的问题。由于某些原因很难验证这种丢失是否发生在与远程服务器的连接中,我现在必须首先检查我的事件处理器类是否有任何问题。我的第一个疑问是,如果订阅信息由于此Dictionary对象的溢出而丢失。有谁有想法吗?谢谢!
更新
也许我应该多谈一下这个场景,因为代码不容易显示。我们曾经使用B的供应商提供的API,将我们的旧SW(我们称之为A)与远程数据服务(称为B)进行通信。但是,由于我们将A更改为64位SW,但为B提供的库仍为32位,因此我们的新64位A不能再使用此库。所以我正在设计一个名为C的32位SW,使用该库连接到B,同时使用WCF保持与64位A的通信。由于C主要是一个pub / sub结构,正如我之前提到的,我使用Dictionary of Dictionary来维护C中的请求和订阅。这就是我们的问题:我们遇到了一些订阅丢失(很长时间没有发布,但在重新初始化订阅后,我们可以在A处获得出版物。我们不容易检查B的反馈,看看是否存在任何错误配置。我的WCF服务日志也没有显示任何错误。我不得不怀疑这个问题只发生在C语言上。我知道多线程问题所以我已经锁定了Dictionary的每个操作。但我想不出什么可能是错的。顺便说一下,它不像C,内存耗尽,C崩溃了。
答案 0 :(得分:6)
如果“溢出”是指“默默地意外丢失数据”,那么不是,不是我所知道的。
如果你的意思是“耗尽系统中的所有内存,直到它崩溃”,那么是的,这是可能的,但这听起来不像你发生的事情。
如果您在没有任何锁定的情况下使用来自多个线程的标准Dictionary<,>
,那么 可能会导致您丢失数据。如果您使用的是.NET 4,则应该使用锁定(小心!)或使用ConcurrentDictionary<,>
。
此外,如果你有任何你没想到的重复密钥,那么如果使用索引器,那么<em>覆盖一个条目的数据与另一个条目。 (如果使用Add
方法则不会 - 它会抛出异常。
基本上我们猜测直到我们看到一些代码或至少获得更多上下文...
答案 1 :(得分:2)
听起来像是竞争条件。
您可能有一些看起来像这样的代码:
if (!myDictionary.ContainsKey(key))
{
//point of interest
myDictionary[key] = new Dictionary<X, Y>()
}
myDictionary[key][innerkey] = innnervalue;
问题在于两个线程使其成为条件下的兴趣点注释。你不打算为同一个键运行那个块两次,但是线程魔法会让它发生。
您可以通过保护锁定后的共享实例来解决此问题:
lock(_theLockInstance)
{
if (!myDictionary.ContainsKey(key))
{
//point of interest
myDictionary[key] = new Dictionary<X, Y>()
}
myDictionary[key][innerkey] = innnervalue;
}
现在,一次只有一个线程可以到达临界区,并且不会创建孤立词典。