继续我最近关于C#和.NET中的锁的思考,
请考虑以下情形:
我有一个类,其中包含一个特定的集合(对于这个例子,我已经使用了一个Dictionary
),它使用一种特定的方法每隔几分钟从一个数据源更新,你可以在下面看到它:
DataTable dataTable = dbClient.ExecuteDataSet(i_Query).GetFirstTable(); lock (r_MappingLock) { i_MapObj.Clear(); foreach (DataRow currRow in dataTable.Rows) { i_MapObj.Add(Convert.ToString(currRow[i_Column1]), Convert.ToInt32[i_Column2])); } }
r_MappingLock是一个专用于锁定关键部分的对象,该部分刷新字典的内容.
i_MapObj是字典对象
i_Column1和i_Column2是数据表的列名,其中包含映射所需的数据.
现在,我还有一个类方法,它接收一个字符串并根据提到的字典返回正确的映射int.
我希望这个方法等到刷新方法完成它的执行,所以乍看之下会考虑以下实现:
lock (r_MappingLock) { int? retVal = null; if (i_MapObj.ContainsKey(i_Key)) { retVal = i_MapObj[i_Key]; } return retVal; }
这将防止在更新字典时出现意外行为和返回值,但会出现另一个问题:由于执行上述方法的每个线程都试图声明锁定,这意味着如果多个线程尝试同时执行此方法,每个都必须等到前一个线程完成执行该方法并尝试声明锁定,这显然是一种不良行为,因为上述方法仅用于读取目的.
我想在类中添加一个布尔成员,该类将被设置为true或false,字典是否正在更新,并在"只读"方法中检查它,但这会产生其他基于竞争条件的问题......
任何想法如何优雅地解决这个问题?
再次感谢,
米奇
看看内置的ReaderWriterLock
.