System.Threading.Tasks in loop problem

I tear off my hair due to the following problem. I have this bit of code that iterates over a list of objects and creates a processing task for each of them.

IList<TileInfo> tiles = tileSource.Schema.GetTilesInView(extent, level); List<Task> renderingTasks = new List<Task>(); foreach (TileInfo info in tiles) { renderingTasks.Add(Task.Factory.StartNew(new Action(delegate { Console.WriteLine(Task.CurrentId +"Info object"+ info.GetHashCode()); } }))); } 

This code prints:

 1Info object36963566 2Info object36963566 3Info object36963566 4Info object36963566 5Info object36963566 6Info object36963566 7Info object36963566 8Info object36963566 9Info object36963566 10Info object36963566 11Info object36963566 12Info object36963566 ... 

As you can see, the problem is that tasks seem to all have a reference to one object!

Why do all tasks use only one object from the list?

thanks for the help

+4
source share
2 answers

I will try to add a few details in an instant, but this is about closing the variable. Change your code to:

Essentially, what you need to do is create a new variable inside the loop, equal to a single declaration outside the loop's internal processing.

 IList<TileInfo> tiles = tileSource.Schema.GetTilesInView(extent, level); List<Task> renderingTasks = new List<Task>(); foreach (TileInfo info in tiles) { TileInfo closingInfo = info; renderingTasks.Add(Task.Factory.StartNew(new Action(delegate { Console.WriteLine(Task.CurrentId +"Info object"+ closingInfo.GetHashCode()); }}))); } 

More details:

ID and close foreach

http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

+5
source

object36963566 should be the last instance in your tile list

This is because foreach works in the current .Net implementation. Although this will be fixed in the future.

You need to read Closing a loop variable that is considered harmful in order to understand how foreach works in this case.

Task.CurrentId +"Info object"+ info.GetHashCode()

info in the above code refers to an element in the tiles list. The delegate being created will not use the info element, referring to its creation (delegate). Rather, it will use the current info value (the value that the information pointed to when the method / delegate actually executes), which explicitly points to the last element of the list. That's why you get this behavior

+4
source

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


All Articles