Multithreaded lambda expressions in C #

I am trying to understand why this program is not working

Expected result: numbers 0-19 in random order What I get when I run: some numbers repeat, sometimes 20 is printed.

Please, help. I tried with lock (obj) in DoSomething (), but that didn't help.

Program

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication2 { public delegate void callbackDelegate(int x); class Program { void processCallback(int x) { Console.WriteLine("IN callback: The value I got is " + x); } static void Main(string[] args) { Program p = new Program(); p.processinThreads(); Console.ReadKey(); } public void DoSomething(int x, callbackDelegate callback) { Thread.Sleep(1000); //Console.WriteLine("I just woke up now " + x); callback(x); } public void processinThreads() { for (int i = 0; i < 20; i++) { Thread t = new Thread(new ThreadStart(()=>DoSomething(i, processCallback))); t.Start(); } } } } 
+4
source share
3 answers
 public void processinThreads() { for (int i = 0; i < 20; i++) { int local = i; Thread t = new Thread(new ThreadStart(()=>DoSomething(local, processCallback))); t.Start(); } } 

Your problem is with lambda closure.

+9
source

You should just use TPL, it is much simpler and recommended for manual flow control :

 Parallel.For(0, 20, x => { Thread.Sleep(1000); Console.WriteLine("IN callback: The value I got is " + x); }); 

It will also be blocked until the loop ends, if you do not want you to use the TPL Task , but I definitely recommend avoiding threads.

+7
source

As Jakub already told you, you need to copy i to another local local variable. In your code, delegates have direct access to i , not copy i , so they print the current value of i , which may be more than when the stream starts. This is called a closure.

+1
source

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


All Articles