如何阻止Timer线程删除该项目,而该项目可能在另一个线程中使用?

时间:2014-11-11 18:39:33

标签: c# multithreading task-parallel-library

我正在为RFID标签编写软件并面临并发问题。

在我的软件中,标签具有用户定义的&#34;生命周期&#34;用分钟计算。一旦标记被读取,它就会放在ConcurrentDictionary<string, Tripple> SeenEnoughDict中(字符串是标记的ID,而Tripplestruct,它会保留System.Threading.Timer以及其中的一些内容标签被看到的次数)。拥有Timer背后的原因,以便标签不会阻塞SeenEnoughDictTimer计划在{1}}生命周期结束时从SeenEnoughDict删除标记。

Parallel.ForEach(_myReaderTC.Cast<Tag>(), t => // _myReaderTC is tag collection that   
                                               //comes back from hardware.
    {
        Tripple temp_tripple;
        // is it in dict ?
        if (SeenEnoughDict.TryGetValue(t.ID, out temp_tripple))
        {
            // Antenna different from prev read ?
            if (temp_tripple.prev_antenna != t.Antenna)
            {
                temp_tripple.prev_antenna = t.Antenna;
                temp_tripple.num_of_times_seen = 1;
                return;
            }
            // antennas are the same, was it seen enough times on particular antenna ?
            if (temp_tripple.num_of_times_seen == _myCaptRespConf.valid_reads)
            {
                // Remove tag id from the dictionary, and delete it's timer
                Tripple temp;
                SeenEnoughDict.TryRemove(t.ID, out temp);
                temp.timer.Dispose();
            }
                // have not seen it enough times 
            else
            {
                temp_tripple.num_of_times_seen++;
                return; 
            }
        }
            // not in the dict 
        else
        {  
            // add the tag's id to the dict and schedule it for deletion
            SeenEnoughDict.TryAdd(t.ID,
                new Tripple(t.Antenna,
                    new Timer(
                              // lamda; schedule tags for deletion
                              (Object tagID) => { 
                                                    Tripple temp;
                                                    // from temp dict 
                                                    SeenEnoughDict.TryRemove((string)tagID, out temp);
                                                    temp.timer.Dispose(); 
                                                },
                              t.ID, // parameter to lambda
                              // _myCaptRespConf.TagPersistence is tags lifecycle time in minutes
                              new TimeSpan(0, 0, _myCaptRespConf.TagPersistence, 0, 0),
                              new TimeSpan(0, 0, 0, 0, -1))));
            return;
        }
    }

如果查看我的代码,很有可能获得竞争:当一个线程通过if (SeenEnoughDict.TryGetValue(t.ID, out temp_tripple)) {....},第二个线程(Timer)启动并删除该项目时字典。

如何正确锁定字典中的项目?

1 个答案:

答案 0 :(得分:1)

一旦你掌握了项目(由TryGetValue返回),另一个线程可能会从字典中删除它,但这不会导致实际对象被销毁,因为你有一个对它的引用。