在C#中为并行线程锁定单个访问变量

时间:2012-01-28 17:39:20

标签: c# .net linq plinq

你好我有这个代码

var queue = new BlockingCollection<int>();
            queue.Add(0);            
            var producers = Enumerable.Range(1, 3)
                .Select(_ => Task.Factory.StartNew(()=>
                    {

                    Enumerable.Range(1, queue.Count)
                            .ToList().ForEach(i =>
                                {

                                    lock (queue)
                                        {
                                            if (!queue.Contains(i))
                                            {
                                                Console.WriteLine("Thread" + Task.CurrentId.ToString());
                                                queue.Add(i);
                                            }
                                        }
                                    Thread.Sleep(100);

                                });

                    }))
                 .ToArray();

            Task.WaitAll(producers);
            queue.CompleteAdding();

                foreach (var item in queue.GetConsumingEnumerable())
                {                    
                        Console.WriteLine(item.ToString());               
                }   

但是我需要每次单个线程向队列广告。添加(i)  要枚举的Enumerable.Range(1,queue.Count),以便代码执行,直到没有更多项添加到队列中。我希望你理解这个问题。 换句话说,我需要这个动作无限地运行,直到我告诉它停止。 有什么建议吗?

2 个答案:

答案 0 :(得分:1)

我很遗憾地说,但我不明白你在没有进一步解释的情况下写这样的东西的动机:(

以下代码是否对您有用?因为我认为不是:P

        int n = 2;

        Task[] producers = Enumerable.Range(1, 3).Select(_ => 
            Task.Factory.StartNew(() =>
                {
                    while (queue.Count < n)
                    {
                        lock (queue)
                        {
                            if (!queue.Contains(n))
                            {
                                Console.WriteLine("Thread" + Task. CurrentId);
                                queue.Add(n);

                                Interlocked.Increment(ref n);
                            }
                        }

                        Thread.Sleep(100);
                    }
                }))
            .ToArray();

我的意思是,它会继续下去。这就像是一个简单的方法,只是在列表中添加数字

请向您解释目标,我们可能会帮助您。

答案 1 :(得分:1)

我知道,你需要的是.NET 4.0附带的BlockingCollection。 它允许实现Producer-Consumer模式。

多个线程或任务可以同时向集合添加项目。多个消费者可以同时删除项目,如果集合变空,消费线程将阻塞并等待生产者添加项目。一遍又一遍......

...直到生产者调用一种特殊的方法来识别结束,说消费者“嘿,停止在那里等待 - 什么都不会再来了!”。

我没有发布代码示例,因为有一些给定的链接。如果您只是谷歌的生产者 - 消费者模式和/或BlockingCollection,您可以找到更多。