How to track the completion of all threads. WITH#

I need to freeze the main thread until the end of the recursion. Recursion depth = number of threads.

code example:

BackgroundWorker backgroundWorker1; Random ran; private void Form1_Load(object sender, EventArgs e) { method(); label1.Text = "Threads is finished"; } private void method() // recursive method { Thread.Sleep(100); backgroundWorker1 = new BackgroundWorker(); backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); backgroundWorker1.RunWorkerAsync(); //Beginning new thread } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { ran = new Random(); Thread.Sleep(ran.Next(500, 1000)); if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion { method(); } } 

When the threads are completed, label1.Text should be set to "Threads is finished" . How it's done?

+4
source share
5 answers

A console PoC application that caches links to all created workers and uses a numerical variable to check how many more are running when this value reaches 0 - the application terminates. Please let me know in case of questions.

 class Program { private static IList<BackgroundWorker> workers; private static Random ran; private static int activeWorkersCount; static void Main(string[] args) { workers = new List<BackgroundWorker>(); DoWork(); while (activeWorkersCount > 0) { Thread.Sleep(200); } Console.WriteLine("Waiting for all workers to finish..."); Console.ReadLine(); } private static void DoWork() // recursive method { Thread.Sleep(100); var newWorker = new BackgroundWorker(); newWorker.DoWork += BackgroundWorkerDoWork; newWorker.RunWorkerCompleted += (o, e) => { Console.WriteLine("[E] Worker finished"); Interlocked.Decrement(ref activeWorkersCount); }; Interlocked.Increment(ref activeWorkersCount); newWorker.RunWorkerAsync(); } private static void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e) { Console.WriteLine("[S] Worker started"); ran = new Random(); Thread.Sleep(ran.Next(500, 1000)); if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion { DoWork(); } } } 
+1
source

When you decide that the recursion stops, you can send a callback to the GUI thread. At the top of my head it will be something like this:

 if(ran.Next(1,5)!=1) { method(); } else { Action action=()=>label1.Text = "Threads is finished"; this.BeginInvoke(action); } 
0
source

1) Create a Label1 update method:

 private void WorkFinished() { if(Label1.InvokeRequired) { Label1.Invoke(WorkFinished); } else { Label1.Text = "Threads is finished"; } } 

2) Call WorkFinished () from backgroundWorker1_DoWork.

0
source

You can use the CountDownEvent class:

Example:

 using (CountDownEvent countdownEvent = new CountdownEvent(numberOfThreads)) { for (int threadIndex= 0; i < numberOfThreads; threadIndex++) ThreadPool.QueueUserWorkItem( th => { DoWork(); countdownEvent.Signal(); }, threadIndex); countdownEvent.Wait(); } Console.WriteLine("All threads complete"); 
0
source

I did this using a variable integer and it works well.

 BackgroundWorker backgroundWorker1; Random ran; long runningThreads = 0; public void Start() { method(); // Console.WriteLine("Threads is finished"); } private void method() // recursive method { Interlocked.Increment(ref runningThreads); Console.WriteLine("New thread started"); Thread.Sleep(100); backgroundWorker1 = new BackgroundWorker(); backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); backgroundWorker1.RunWorkerAsync(); //Beginning new thread } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { ran = new Random(); Thread.Sleep(ran.Next(500, 1000)); if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion { method(); } Finished(); } private void Finished() { Interlocked.Decrement(ref runningThreads); if (Interlocked.Read(ref runningThreads) == 0) { Console.WriteLine("Threads is finished"); } } 
0
source

Source: https://habr.com/ru/post/1439789/


All Articles