2

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.

ebb
  • 9,297
  • 18
  • 72
  • 123
Mike
  • 83
  • 6
  • 1
    More information is needed , may be you can add more details to your question as in the current format it is difficult to understand what you trying to acehive – TalentTuner Dec 24 '10 at 08:02
  • Why don't you just use `while (!close_thread)` in the loop? – jgauffin Dec 24 '10 at 08:13
  • 1
    I really don't know what else you want me to add. I am running this on the xbox so using a ThreadPool is out of the question. I need a Producer/Consumer task queue which can run on 4 threads. Once in a while I have to run a task which requires that no other tasks are running on any of the threads while it runs. – Mike Dec 24 '10 at 08:14
  • 1
    @jgauffin I cannot since it is an unsafe variable. – Mike Dec 24 '10 at 08:16

4 Answers4

1

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

MSDN

Anton
  • 5,323
  • 1
  • 22
  • 25
  • I cannot use the threadpool. Its just horrible on the xbox 360. – Mike Dec 24 '10 at 07:55
  • I do use a custom thread pool http://www.codeproject.com/KB/threads/smartthreadpool.aspx - Is this usable on your platform? – Uwe Keim Dec 24 '10 at 08:13
  • 1
    I do not need a thread pool. It is much smarter to manage your own threads on xbox. – Mike Dec 24 '10 at 08:26
  • 1
    @mike if it's so much smarter to manage your own threads then why are you asking for help? – David Heffernan Dec 24 '10 at 08:31
  • In that case you may want to look into keeping track of IAsyncResult instances and feed those to AsyncCallback delegates. Been quite a while since I worked with that though, but you may find what you;re looking for looking into those at MSDN. – Anton Dec 24 '10 at 08:38
0

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;
        }
    }
Jason Li
  • 1,528
  • 1
  • 12
  • 20
0

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.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
-1

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.

Nikunj
  • 3,100
  • 2
  • 20
  • 19