代码之家  ›  专栏  ›  技术社区  ›  rupweb

实现并发堆栈的阻塞集合

c#
  •  -1
  • rupweb  · 技术社区  · 4 年前

    我有一个类来保存一堆字符串,以便在UI上绘制,如果没有项,我想用它来阻止,如果有很多项,则使用后进先出。

    internal class PaintStack
    {
        private BlockingCollection<PaintString> paintStack;
    
        public PaintStack()
        {
            paintStack = new BlockingCollection<PaintString>(new ConcurrentStack<PaintString>());
        }
    
        public void Add(PaintString p)
        {
            paintStack.Add(p);
        }
    
        public PaintString Take()
        {
            return paintStack.Take();
        }
    }
    

    当我 add 集合中的新对象我看到所有对象都与新对象相同。发生什么事?

    新的弦乐 price 价值 1450.4

    new price

    现在,整个并发堆栈的代价是 1450.4

    stack

    然后下一个字符串将与 价格 价值 1460.4

    new price

    整个堆栈的值似乎为 1460.4

    stack

    出什么事了?

    1 回复  |  直到 4 年前
        1
  •  2
  •   JonasH    4 年前

    您可能正在将对同一对象的多个引用添加到列表中。因此,当您更改对象时,列表中的所有内容都会受到影响,因为它们都指向同一个对象。

    要解决这个问题,我建议使用不可变对象或 record 。因此,您不需要更改现有对象,而是使用请求的更改创建一个新对象。这巧妙地避免了此类问题,并有助于确保线程安全。

    此外,正如评论中提到的,堆栈是后进先出(LIFO)。如果需要FIFO,请使用ConcurrentQueue。

    此外,如果不编写多线程代码,则不需要concurrent*。关于多线程代码,我的标准建议是,只有在您熟悉风险以及如何减轻风险的情况下,才执行该操作。多线程因引起严重的、难以复制的错误而臭名昭著。