背景:上游给出图像检测的结果,屏幕上的像素位置,我结合信息放在ConcurrentDictionary中,每次这个检测结果都是有变化的,没有好的办法去更新,只能清空重新赋值。。。
两个线程:
线程A:先清空这个ConcurrentDictionary,然后给里面写数据(两个操作在一个方法里)
//定义
public static ConcurrentDictionary<string,Point> info = new ConcurrentDictionary<string,Point>();
public static void funcA(){
info.Clear();
.........
info.tryAdd(string,point);
}
线程B遍历这个ConcurrentDictionary
public static void funB(){
foreach(var key in className.info.Keys){
string theKey=key;//就是这里会抛出空指针异常,说什么 未将对象设置到引用的实例什么的
Point p=className.info[k];
......................................
}
}
没有好的办法取更新是什么情况,ConcurrentDictionary不是有好几个更新方法么
而且,为什么要清空?直接创建一个新的ConcurrentDictionary替换掉之前那个不行么
还有,这个为什么要用两个线程
图像识别,结果不稳定,一会有一会没有,位置也不稳定。没有规律去更新。
不能直接替换掉吧,因为这个是个公共变量,好多地方都要用到的,
图像识别是一个线程,这个info就是在图像识别线程里的,识别结果
另一个负责调用paint方法,将识别的结果展示在picturebox中,所以就用了两个线程
@小草上飞飞: 公共变量就是麻烦
在线程B,直接调用className.info.ToArray()试一下,ToArray方法应该比遍历Keys靠谱一些
@拓拓: 你看我其他的提问,我都要哭了,多线程这个ConcurrentDictionary问题,前几个问题是别人代码里的,直接从别的系统摘出来给我。我搞了好久,勉强暂时不出问题,运行时间长了就down了,我一个学Java的做C#还是有些麻烦
@拓拓: 按道理,ToArray()应该是不会出问题,因为保存的是当时的副本
@小草上飞飞: 讲道理你这一个线程写一个线程读的场景就不该用ConcurrentDictionary,这里如果用一个ConcurrentQueue存数据,你就不需要考虑字典的更新问题。
然后上游搞出来的数据有没有问题一目了然。
这样看起来才合理一点。
多线程的东西,要尽可能的避免读写同一个变量,如果可以,全都是只读的最好。
@小草上飞飞: 还有,静态全局变量也不是不能替换,就是麻烦一点,需要仔细检查一下
@拓拓: 可以试一试ConcurrentQueue
简单点就加个锁吧