自定义线程安全的Dictionary
我们说一个数据结构是线程安全指的是同一时间只有一个线程可以改写它。这样即使多个线程来访问它,它也不会产生对线程来说很意外的数据。
C#中的Dictionary不是线程安全的,我在下面这个例子中,把一个Dictionary对象作为了全局的static变量。会有多个线程来访问它。所以我需要包装一下.net自带的Dictionrary.
发生冲突的部分无非是写的地方,所以在离写Dictionary最近的地方加一个锁。其他的外层代码可以自带的Dictionary相同了。
我们看Dictionary的实现接口,
syncRoot是自定义SafteDictionary内的互斥对象,哪个线程拿到它才可以对内部的Dictionary进行操作。
比如new Dictionary().Add加一个syncRoot的锁,变成
public void Add(TKey key, TValue value)
{
lock (syncRoot)
{
d.Add(key, value);
}
}
同一个时间点只能有一个线程能够访问d.Add(key, value);
定义一个全局的SafeDictionray对象,则它不会同时被多个线程操作。
附件中的例子中定义了一个全局的SafeDictionray对象Helper.DicNetStatus,表示IP地址对应设备的连接状态,IP为Key,True/False为Value,在程序启动时有一个DealingData线程不停的在刷新Helper.DicNetStatus的值,每隔1秒刷一次。MainForm是主界面线程。另外有一个MainForm的后台线程DisplayDicStatus不停的在读取Helper.DicNetStatus的值,每隔1秒刷一次,刷一次就反映到界面上来,可以显示出某个IP设备的连接状态。就像QQ列表中根据不同头像显示好友的不同连线状态一样。
总结一下附件例子中涉及到的知识点:
1,如果解决多线程操作某个全局数据对象的问题。解决方法:自定义一个线程安全的数据对象类。
2,如何跨线程调用界面控件。解决方法:this.Invoke(设置界面控件的代理)
附上代码,请指正。SafeDictionary的例子