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

本文关键字:线程 另一个 Timer 何防止 删除 | 更新日期: 2023-09-27 18:30:11

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

在我的软件中,标签具有用户定义的以分钟为单位的"寿命"。一旦读取了标签,它就会被放在ConcurrentDictionary<string, Tripple> SeenEnoughDict中(字符串是标签的ID,而Tripple是保持System.Threading.Timerstruct,还有一些东西,比如标签被看到的次数)。拥有Timer的原因,这样标签就不会阻塞SeenEnoughDictTimer调度要在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)启动并从字典中删除该项。

我应该如何正确地锁定字典中的项目?

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

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