How to ensure that a thread runs exactly after a certain number of other threads have finished?

I have a class in C #, for example:

public MyClass
{
   public void Start() { ... }

   public void Method_01() { ... }
   public void Method_02() { ... }
   public void Method_03() { ... }
}

When I call the "Start ()" method, the outer class starts working and creates many parallel threads, which these parallel threads call the form "Method_01 ()" and "Method_02 ()" above the class. after the work of the external class, "Method_03 ()" will be executed in another parallel thread.

The streams "Method_01 ()" or "Method_02 ()" are created before the creation of the stream Method_03 (), but there is no guarantee that you need to finish before the start of the stream "Method_03 ()". I mean that "Method_01 ()" or "Method_02 ()" will lose the processor turn, and "Method_03" will return the processor and will end completely.

"()" , "Method_01" "Method_02()" . , , , "Method_03()" , "Method_01()" "Method_02()" ,.

+3
5

:

  • Thread Join Method_03.
  • CountdownEvent Wait Method_03.
  • ManualResetEvent Method_01 Method_02 WaitHandle.WaitAll Method_03 ( ).

CountdownEvent, - .

public class MyClass
{
  private CountdownEvent m_Finished = new CountdownEvent(0);

  public void Start()
  {
    m_Finished.AddCount(); // Increment to indicate that this thread is active.

    for (int i = 0; i < NUMBER_OF_THREADS; i++)
    {
      m_Finished.AddCount(); // Increment to indicate another active thread.
      new Thread(Method_01).Start();
    }

    for (int i = 0; i < NUMBER_OF_THREADS; i++)
    {
      m_Finished.AddCount(); // Increment to indicate another active thread.
      new Thread(Method_02).Start();
    }

    new Thread(Method_03).Start();

    m_Finished.Signal(); // Signal to indicate that this thread is done.
  }

  private void Method_01()
  {
    try
    {
      // Add your logic here.
    }
    finally
    {
      m_Finished.Signal(); // Signal to indicate that this thread is done.
    }
  }

  private void Method_02()
  {
    try
    {
      // Add your logic here.
    }
    finally
    {
      m_Finished.Signal(); // Signal to indicate that this thread is done.
    }
  }

  private void Method_03()
  {
    m_Finished.Wait(); // Wait for all signals.
    // Add your logic here.
  }
}
+3

Tasks. , Method01 Method02 - ( , ):

int cTaskNumber01 = 3, cTaskNumber02 = 5;
Task tMaster = new Task(() => {
    for (int tI = 0; tI < cTaskNumber01; ++tI)
        new Task(Method01, TaskCreationOptions.AttachedToParent).Start();
    for (int tI = 0; tI < cTaskNumber02; ++tI)
        new Task(Method02, TaskCreationOptions.AttachedToParent).Start();
});
// after master and its children are finished, Method03 is invoked
tMaster.ContinueWith(Method03);
// let it go...
tMaster.Start();
+2

static volatile int threadRuns, Method_01 Method_02. threadRuns :

...
lock(typeof(MyClass)) {
    --threadRuns;
}
...

Method_03 , threadRuns 0, :

while(threadRuns != 0)
   Thread.Sleep(10);

quesiton?

+1

, ManualResetEvent ( ) - WatHandle Method_01 Method_02, Thread_03 WaitHandle.WaitAll .

, Thread, Method_01 Method_02, Thread_03 Thread.Join, . , , , Method_01 Method_02, , , .

+1

Barrier , .NET 4.0. .

You can do something like the following code, but this is mostly useful when synchronizing different processing threads.

 public class Synchro
    {
        private Barrier _barrier;          

        public void Start(int numThreads)
        {
            _barrier = new Barrier((numThreads * 2)+1);
            for (int i = 0; i < numThreads; i++)
            {
                new Thread(Method1).Start();
                new Thread(Method2).Start(); 
            }
            new Thread(Method3).Start();
        }

        public void Method1()
        {
            //Do some work
            _barrier.SignalAndWait();
        }

        public void Method2()
        {
            //Do some other work.
            _barrier.SignalAndWait();
        }

        public void Method3()
        {
            _barrier.SignalAndWait();               
            //Do some other cleanup work.
        }
    }

I would also like to suggest that, since your expression about the problem was rather abstract, frequently occurring problems solved with the countdownevent function are now better solved using the new Parallel or PLINQ features. If you really handled a collection or something in your code, you might have something like the following.

 public class Synchro
    {
        public void Start(List<someClass> collection)
        {
            new Thread(()=>Method3(collection));
        }

        public void Method1(someClass)
        {
            //Do some work.               
        }

        public void Method2(someClass)
        {
            //Do some other work.                
        }

        public void Method3(List<someClass> collection)
        {
            //Do your work on each item in Parrallel threads.
            Parallel.ForEach(collection, x => { Method1(x); Method2(x); });
            //Do some work on the total collection like sorting or whatever.                
        }
    }
+1
source

All Articles