I do not think how to implement it.

There is a workflow called N times at the same time and a dispatcher thread. Both contain some cycles.

Dispatcher Thread:

  1. Performs 1 iteration.
  2. Gives permission to workflows.
  3. Waiting for each of them to perform 1 iteration.

Workflow cycle:

  1. Waiting for permission from the dispatcher.
  2. Performs 1 iteration.
  3. Reports the completion of an iteration.

They said that it can be implemented using a semaphore, but I can’t figure out how. I just understood how it can be used to restrict access to a code fragment, but what about the case described above?

It is necessary to use streams.

PS: if someone is confused by the lack of a description of exiting the cycles, they are finite, simply, it does not matter here.

Upd: it seems that I did not quite understand. Threading methods look like this:

//поток-диспетчер static void ProtocolThread(object input) { //... do { //... //здесь он должен давать разрешение и ждать } while (!complited); return; } //рабочий поток (вызывается несколько таких параллельно) static void ThreadMethod(object input) { //... do { //здесь он должен ждать разрешение //... //здесь сообщить о завершении итерации (если это необходимо) } while (!complited); return; } 

Threads start like this:

 ThreadPool.QueueUserWorkItem(new WaitCallback(ProtocolThread)); 
  • Are you accessing the completed variable without synchronization? Oh well. - VladD
  • No, there are actually different expressions. I wrote this for short. - InfernumDeus

3 answers 3

An additional answer for the case when the workflows are not the same - and additional protection is required from performing two tasks at once.

  1. WaitHandle has a method like SignalAndWait. This method works atomically. If you apply it in workflows over two semaphores, this will ensure that all workflows have fallen asleep by the time the dispatcher wakes up.
  2. Also, semaphores have a method that allows you to make the Release operation immediately N times, also atomically. The application of this method at the moment when all workflows are asleep will wake them all at the same time.

With the help of these two tricks available due to the wealth of WinAPI, you can solve the problem without entering additional primitives.

    You should not use low-level constructs such as semaphores and streams. C # has more convenient constructs.

    If you need to perform only one task, do this:

     void Iteration() { ... } // main Iteration(); var tasks = new List<Task>(); for (int i = 0; i < n; i++) tasks.Add(Task.Run(Iteration)); await Task.WhenAll(tasks); 

    If you really need threads, then

     Iteration(); var threads = new List<Thread>(); for (int i = 0; i < n; i++) { var t = new Threads(Iteration); t.Start(); threads.Add(t); } foreach (var t in threads) t.Join(); 

    If the workflow is one, you can use the producer-consumer:

     BlockingCollection<int> q = new BlockingCollection<int>(); // main var t = new Thread(Consumer); t.Start(); Iteration(); for (int i = 0; i < n; i++) q.Add(i); q.CompleteAdding(); // останавливаем t.Join(); // ---------------------------------- void Consumer() { foreach (var n in q.GetConsumingEnumerable()) Iteration(); } 
    • In this case, the task requires the use of threads, so this option is not suitable. - InfernumDeus
    • one
      Why? Study assignment? - VladD
    • Yes, training. In this case, nothing really explained. Did not quite understand your way. What does Iteration(); mean Iteration(); ? Added to the question a general view of the thread methods. Please show them by example. - InfernumDeus
    • @InfernumDeus: Well, your condition says “performs 1 iteration”. This is the very iteration. - VladD

    Get two semaphores. One semaphore problem is not solved.

    The first semaphore will be used to issue a work permit. The second is for signaling the end of processing.

    And then do as written in the assignment. There and so everything is already in steps painted.

    • For sure. Thank. While having dinner half an hour ago, I realized exactly the same thing. - InfernumDeus
    • Although again not fully understood. How to organize it taking into account the fact that the number of workflows is arbitrary (N)? Say, at the end of the dispatcher thread, I will completely release the semaphore by N units. As soon as this happens, the worker threads that are currently waiting will start the loop. But what if one such thread has time to complete the iteration before any other one even has time to go to the loop? Is it possible that after one resolution one stream will perform 2 iterations, and the other 0? - InfernumDeus
    • Are the streams the same? Do the same thing? Then what's the problem? :) - Pavel Mayorov
    • Well, they are the same, but they must simultaneously process a sequence of different data of the same type. The task assumes a strict sequence of actions: the dispatcher thread has output the contents of a global variable (array) -> each workflow has performed exactly one iteration -> the dispatcher has output ... and so on. - InfernumDeus