D
D
Drunk Workaholic2019-01-16 03:30:14
.NET
Drunk Workaholic, 2019-01-16 03:30:14

How to start multiple threads in C# (SOLVED)?

I'm learning multithreading. Faced the following problem. Here is the code:

public class WORK{
        private int number;
        public Action<int> delegWork; // Обобщ.делегат
 
        public void Working(int num){
                this.number += num; // Какая-то полезная работа с результатов переданным в this.number
                ThreadPool.QueueUserWorkItem((object n) => { this.delegWork((int)n); }, this.number ); //Запуск делегата
        }
}
 
public class ANALYSIS{
        private readonly Form _form;  // Windows Form
        public Action<int> delegAnalysis; // Обобщ.делегат
 
        public ANALYSIS(Form form){
                this._form = form;
                this.Make();
        }
        
        // Метод класса, в котором происходит присвоение делегату анон.метода
        private void Make(){
                this.delegAnalysis += (number) => {
                      this._form.Invoke((MethodInvoker)delegate{
                           Thread.Sleep(25);  // Эмуляция полезной работы
                           Console.WriteLine ("Number: " + number);
                      });
                };
        }        
}
.....
 
/* В основном потоке */
 
WORK worker = new WORK();
ANALYSIS analyzer = new ANALYSIS(this); // В конструктор передаем текущий Windows Form приложения 
 
 
worker.delegWork += (number) => { analyzer.delegAnalysis(number); };
 
//Цикл в основном потоке (например построчное чтение из файла и т.п.)
for(int i = 0; i < 500; i++){
        worker.Working(i);
}

Code description - some useful work is done in the Working method of the WORK class, then the result of this work is sent to the anon.method of the ANALYSIS class in which the results of the work of the WORK class are analyzed using the delegWork and delegAnalysis delegates. Accordingly, the work itself can be performed faster than its analysis, but the analysis itself must go strictly one after the other, and not chaotically. Those. the next method called through delegAnalysis must wait for the results of the previous call to delegAnalysis.
I implemented multithreading using ThreadPool.QueueUserWorkItem. it is more economical. In this case, Console.WriteLine works in some separate thread / threads, and in the console I see something like this:
1
3
6
4
2
5
...
500
489
499

As you can see, the numbers are not in order .
The question is - how can I make threads sequentially executed? For the next thread to wait until the previous one finishes its work. And preferably as less resource intensive as possible.
PS. At the moment I’m looking at recursion and something like Task Continuewith (or await / join), but they can’t figure out how to assemble and wrap everything together.
At the moment, I decided this way:
Using BlockingCollection and launching the second thread in the constructor when initializing the WORK class.
public class WORK{
        private BlockingCollection<Func<Task>> _collection = new BlockingCollection<Func<Task>>();
        private Thread ConsumerThread;
 
        private int number;
        public Action<int> delegWork; // Обобщ.делегат
        
        //Конструктор
        public WORK(){
                this.ConsumerThread = new Thread(this.LaunchThread);
                this.ConsumerThread.Start();
        }
 
        public void Working(int num){
                this.number += num; // Какая-то полезная работа с результатов переданным в this.number
                int index = this.number; this._collection.Add(new Func<Task>(async () => { this.delegWork(index); })); // Добавляем делегат во второй поток через BlockingCollection
        }
        
        // Метод для второго потока 
        private async void LaunchThread()
        {
            while (true)
            {
                var processTask = this._collection.Take();
                await Task.Run(processTask);
            }
        }
}
 
public class ANALYSIS{
        private readonly Form _form;  // Windows Form
        public Action<int> delegAnalysis; // Обобщ.делегат
 
        public ANALYSIS(Form form){
                this._form = form;
                this.Make();
        }
        
        // Метод класса, в котором происходит присвоение делегату анон.метода
        private void Make(){
                this.delegAnalysis += (number) => {
                      this._form.Invoke((MethodInvoker)delegate{
                           Console.WriteLine ("Number in analyzer: " + number);
                      });
                };
        }        
}
.....
 
/* В основном потоке */
 
WORK worker = new WORK();
ANALYSIS analyzer = new ANALYSIS(this); // В конструктор передаем текущий Windows Form приложения 
 
//Подписываем делегат
worker.delegWork += (number) => { analyzer.delegAnalysis(number); };
worker.delegWork += (number) => { Console.WriteLine ("Number: " + number); };
 
//Второй поток для задачи (например построчное чтение из файла и т.п.)
new Thread(() =>
{
     for(int i = 0; i < 500; i++){
             worker.Working(i);
     }
}).Start();

Answer the question

In order to leave comments, you need to log in

2 answer(s)
G
Griboks, 2019-01-16
@Griboks

The question is - how can I make threads sequentially executed? For the next thread to wait until the previous one finishes its work. And preferably as less resource intensive as possible.

Below is the best option:
//Цикл в основном потоке
for(int i = 0; i < 500; i++) Console.WriteLine(i);

F
FFoxDiArt, 2019-01-16
@FFoxDiArt

You already decide what you need: either to execute in parallel, or sequentially. Why create parallel code that behaves like serial but with wild overhead?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question