我如何等待所有其他线程完成任务?

时间:2010-12-24 07:44:19

标签: c# multithreading xbox360

我有几个线程使用类似于下面代码的东西从队列中消耗任务。问题是有一种类型的任务在处理任何其他任务时无法运行。

这就是我所拥有的:

while (true) // Threaded code
{
    while (true)
    {
        lock(locker)
        {
            if (close_thread)
                return;

            task = GetNextTask(); // Get the next task from the queue
        }

        if (task != null)
            break;

        wh.WaitOne(); // Wait until a task is added to the queue
    }

    task.Run();
}

这就是我需要的东西:

while (true)
{
    while (true)
    {
        lock(locker)
        {
            if (close_thread)
                return;

            if (disable_new_tasks)
            { 
                task = null; 
            }
            else
            {
                task = GetNextTask();
            }
        }

        if (task != null)
            break;

        wh.WaitOne();
    }

    if(!task.IsThreadSafe())
    {
        // I would set this to false inside task.Run() at 
        // the end of the non-thread safe task
        disable_new_tasks = true;  
        Wait_for_all_threads_to_finish_their_current_tasks(); 
    }

    task.Run();
}

问题是我不知道如何在不造成混乱的情况下实现这一目标。

4 个答案:

答案 0 :(得分:1)

尝试使用TreadPool,然后使用WaitHandle.WaitAll方法确定所有线程都已完成执行。

MSDN

答案 1 :(得分:0)

WaitHandle.WaitAll(autoEvents); 也许这就是你想要的。

class Calculate
    {
        double baseNumber, firstTerm, secondTerm, thirdTerm;
        AutoResetEvent[] autoEvents;
        ManualResetEvent manualEvent;

        // Generate random numbers to simulate the actual calculations.
        Random randomGenerator;

        public Calculate()
        {
            autoEvents = new AutoResetEvent[]
            {
                new AutoResetEvent(false),
                new AutoResetEvent(false),
                new AutoResetEvent(false)
            };

            manualEvent = new ManualResetEvent(false);
        }

        void CalculateBase(object stateInfo)
        {
            baseNumber = randomGenerator.NextDouble();

            // Signal that baseNumber is ready.
            manualEvent.Set();
        }

        // The following CalculateX methods all perform the same
        // series of steps as commented in CalculateFirstTerm.

        void CalculateFirstTerm(object stateInfo)
        {
            // Perform a precalculation.
            double preCalc = randomGenerator.NextDouble();

            // Wait for baseNumber to be calculated.
            manualEvent.WaitOne();

            // Calculate the first term from preCalc and baseNumber.
            firstTerm = preCalc * baseNumber * 
                randomGenerator.NextDouble();

            // Signal that the calculation is finished.
            autoEvents[0].Set();
        }

        void CalculateSecondTerm(object stateInfo)
        {
            double preCalc = randomGenerator.NextDouble();
            manualEvent.WaitOne();
            secondTerm = preCalc * baseNumber * 
                randomGenerator.NextDouble();
            autoEvents[1].Set();
        }

        void CalculateThirdTerm(object stateInfo)
        {
            double preCalc = randomGenerator.NextDouble();
            manualEvent.WaitOne();
            thirdTerm = preCalc * baseNumber * 
                randomGenerator.NextDouble();
            autoEvents[2].Set();
        }

        public double Result(int seed)
        {
            randomGenerator = new Random(seed);

            // Simultaneously calculate the terms.
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateBase));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateFirstTerm));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateSecondTerm));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateThirdTerm));

            // Wait for all of the terms to be calculated.
            **WaitHandle.WaitAll(autoEvents);**

            // Reset the wait handle for the next calculation.
            manualEvent.Reset();

            return firstTerm + secondTerm + thirdTerm;
        }
    }

答案 2 :(得分:0)

您可以将此视为类似于允许任意数量的读者或一个作者的数据结构。也就是说,任意数量的线程都可以读取数据结构,但写入数据结构的线程需要独占访问。

在您的情况下,您可以运行任意数量的“常规”线程,或者您可以拥有一个需要独占访问权限的线程。

.NET具有ReaderWriterLockReaderWriterLockSlim类,您可以使用它们来实现这种共享。不幸的是,xbox上都没有这些类。

但是,可以从MonitorManualResetEvent对象的组合实现读取器/写入器锁定。我没有C#示例(为什么我会,因为我可以访问本机对象?),但是有一个simple Win32 implementation不应该非常难以移植。

答案 3 :(得分:-1)

你可以使用这样的东西,

ExecutorService workers = Executors.newFixedThreadPool(10); 

   for(int i=0; i<input.length; i++) {
       Teste task = new Teste(rowArray,max);//your thread class
       workers.execute(task);
   }

   workers.shutdown();//ask for shut down
   while(!workers.isTerminated()) {//wait until all finishes.

  try {
      Thread.sleep(100);//
      } catch (InterruptedException exception) {
      }   
      System.out.println("waiting for submitted task to finish operation");
    }

希望得到这个帮助。