我估计应该是很简单的一个问题,请各位帮忙解惑!有一个list,需要把它的每个元素进行一下处理,但是在处理过程中可能生成新的元素又加到这个list里来,因此其大小是不固定的
现在我想采用并行计算来处理这个list,初步思路是:假设有两个核,我把这个list平均分成两部分作为两个task,然后调用parallel.invoke,但是这两个list中,每个list生成新的元素的数量是不一定的,也就是说,也许运行过程中,task2还有好多元素没有处理,但task1开始闲着了请问这种情况该怎么处理?我用的方式是最佳方式么?

解决方案 »

  1.   

    不要用List用Queue 
    两边线程同时
    while(Queue.Count>0)
    {
       lock(Queue)
       {
         xxx=Queue.DeQueue();
       }
    }另外你就随边向Queue.EnQueue(Item)就行了。
      

  2.   

    google "生产者-消费者问题 csharp"
      

  3.   

    http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx#vcwlkthreadingtutorialexample2synchronizingExample 2: Synchronizing two threads: a producer and a consumer
    标准做法。
      

  4.   


    那意思是,如果我有四个核,那么就重复四边
    谢谢,请问用list为什么不行呢?我看这些功能用list都能实现啊
      

  5.   


    Queue好处是,某项执行完了,就出队,List不会,如果用List你要做好几个判断
      

  6.   

    使用Monitor实现多线程的生产者消费者模式(C#)
    最近在实现socket服务器的延时任务系统功能:即上层应用不断将需要过一段时间执行的功能委托给任务系统,任务系统再在其自己维护的线程中扫描待执行任务列表,如果到达执行时间,则执行此任务。经过几次实践发现,使用Monitor的Wait, Pulse 和PulseAll方法实现一种生产者/消费者模式,是个不错的解决方案。
    Monitor的Wait, Pulse 和 PulseAll用于在多线程通信。如果一个线程调用了Wait,则该线程将阻塞,Monitor将被释放,直到有其他线程调用了Pulse 或者 PulseAll。Pulse只唤醒一个正在Wait的线程,而PulseAll则将唤醒所有等待Monitor的线程。
    这些方法最常用于生产者/消费者的情形:一个线程把工作项放入队列,其他线程将工作项取出。消费线程通常一直取出工作项直到消耗光,然后等待锁,生产线程则在将工作项添加进队列后,调用Monitor的Pulse使得消费线程开始工作。
    下面的代码演示了这些方法的简单用法:
    using System; 
    using System.Collections; 
    using System.Threading; public class Test 

        static ProducerConsumer queue;
        static void Main()
        { 
            queue = newProducerConsumer(); 
            new Thread(newThreadStart(ConsumerJob)).Start(); 
            Random rng = new Random(0); 
            for(int i=0; i < 10; i++) 
            {
                Console.WriteLine ("Producing {0}", i); 
                queue.Produce(i); 
                Thread.Sleep(rng.Next(1000)); 
             } 
        }     static void ConsumerJob() 
        { 
            // Make sure we get a different random seed from the
            // first thread
            Random rng = newRandom(1);        // We happen to know we've only got 10 
            // items to receive
            for(inti=0; i < 10; i++)
            {
                object o = queue.Consume();
                Console.WriteLine ("\t\t\t\tConsuming {0}", o); 
                Thread.Sleep(rng.Next(1000)); 
            }
        }
    }public class ProducerConsumer 

        readonly object listLock = new object(); 
        Queue queue = new Queue();     public void Produce(objecto) 
        { 
            lock(listLock) 
            { 
                queue.Enqueue(o);             // We always need to pulse, even if the queue wasn't
                // empty before. Otherwise, if we add several items
                // in quick succession, we may only pulse once, waking
                // a single thread up, even if there are multiple threads
                // waiting for items.
                Monitor.Pulse(listLock); 
            } 
        }     public object Consume() 
        { 
            lock(listLock) 
            { 
                // If the queue is empty, wait for an item to be added
                // Note that this is a while loop, as we may be pulsed
                // but not wake up before another thread has come in and
                // consumed the newly added object. In that case, we'll
                // have to wait for another pulse.
                while(queue.Count==0) 
                { 
                    // This releases listLock, only reacquiring it
                    // after being woken up by a call to Pulse
                    Monitor.Wait(listLock); 
                } 
                return queue.Dequeue(); 
            } 
        }
    }
    运行上述代码后,将产生类似下面的输出:
    Producing 0 
                                 Consuming 0 
    Producing 1 
                                Consuming 1 
    Producing 2 
                                Consuming 2 
    Producing 3 
                                Consuming 3 
    Producing 4 
    Producing 5 
                                Consuming 4 
    Producing 6
                                Consuming 5 
                                Consuming 6 
    Producing 7 
                                Consuming 7 
    Producing 8 
                                Consuming 8 
    Producing 9 
                                Consuming 9
      

  7.   

    不是的
    我是意思,你在从List取出 取什么由你决定,取出后插到队列里。明白?
      

  8.   


    谢谢兄台。
    我还有个问题,我使用.net 4.0中的TPL实现这个的,我的做法是定义了两个task,每个task都从一个公共的queue里取值,但遇到的问题是:刚开始queue里只有一个元素,第一个task取到这个元素后,就把它删了,但这时第一个task还在运行,还没有生成新的元素,第二个task也开始了,它看见queue是空的,就自动结束了
    于是,程序永远都在第一个task里执行,又成了串行模式了
    请问,该怎么避免这种情况呢?
      

  9.   


    不要用task,直接用Thread吧 你所但心的那是没必要的   while(queue.Count==0) 
                { 
                    // This releases listLock, only reacquiring it
                    // after being woken up by a call to Pulse
                    Monitor.Wait(listLock);  《-这句是指如果queue为空了,就让线程等待,直到有新的数据装入到queue里面线程才会继续下去。 不用但心他会退出
                } 
      

  10.   

    while(true)
    {
    lock(queue)....
    if(Queue.Count==list.count)break;
    }
      

  11.   

    错了,是搞一个计数在里面
    if(计数器==list.count)break;
      

  12.   


    原来是这样多谢
    那么请问,task最后要落到thread上来,是不是所有用task实现的,都能用thread实现?
    用thread应该比用task更快吧?