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

发布于 2024-10-08 18:23:42 字数 1196 浏览 2 评论 0原文

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

这就是我所拥有的:

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();
}

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

I have several threads consuming tasks from a queue using something similar to the code below. The problem is that there is one type of task which cannot run while any other tasks are being processed.

Here is what I have:

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();
}

And this is kind of what I need:

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();
}

The problem is I don't know how to achive this without creating a mess.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

葬﹪忆之殇 2024-10-15 18:23:42

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

MSDN

Try looking to using a TreadPool and then using the WaitHandle.WaitAll method to determine that all threads have finished executing.

MSDN

笙痞 2024-10-15 18:23:42

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;
        }
    }

WaitHandle.WaitAll(autoEvents); Maybe this is what you want.

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;
        }
    }
诺曦 2024-10-15 18:23:42

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

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

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

但是,可以通过 MonitorManualResetEvent 对象的组合来实现读取器/写入器锁定。我没有 C# 示例(既然我可以访问本机对象,为什么要这样做?),但是有一个 简单的 Win32 实现,移植起来应该不会太困难。

You can think of this as similar to a data structure that allows any number of readers, or one writer. That is, any number of threads can read the data structure, but a thread that writes to the data structure needs exclusive access.

In your case, you can have any number of "regular" threads running, or you can have one thread that requires exclusive access.

.NET has the ReaderWriterLock and ReaderWriterLockSlim classes that you could use to implement this kind of sharing. Unfortunately, neither of those classes is available on the xbox.

However, it possible to implement a reader/writer lock from a combination of Monitor and ManualResetEvent objects. I don't have a C# example (why would I, since I have access to the native objects?), but there's a simple Win32 implementation that shouldn't be terribly difficult to port.

孤蝉 2024-10-15 18:23:42

你可以使用这样的东西,

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");
    }

希望这有帮助。

you can use something like this,

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");
    }

Hope this help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文