0
private static int[] Sort(int[] arr)
        {
            int temp;
            int[] result = new int[arr.Length];
            Array.Copy(arr, result, arr.Length);

            for (int i = 0; i < result.Length - 1; i++)
            {

                for (int j = i + 1; j < result.Length; j++)
                {

                    if (result[i] > result[j])
                    {
                        temp = result[i];
                        result[i] = result[j];
                        result[j] = temp;
                    }
                }
            }

            return result;
        }

public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize)
        {
            return source
                .Select((x, i) => new { Index = i, Value = x })
                .GroupBy(x => x.Index / chunkSize)
                .Select(x => x.Select(v => v.Value).ToList())
                .ToList();
        }
...
List<List<int>> unsortedLists = list.ChunkBy(chunkSize);
            int count = unsortedLists.Count;
            List<List<int>> lists = new List<List<int>>();

            Task<List<int>>[] tasks = new Task<List<int>>[count];
            //from 0 to 9
            for (int i = 0; i < count; i++)
            {
                tasks[i] = new Task<List<int>>(() =>
                {
                    lists[i] = Sort(unsortedLists[i].ToArray()).ToList(); //out of range exception i = 10
                    return lists[i];
                });          
            }

            for(int i = 0; i < count; i++)
            {
                tasks[i].Start();
            }

            for(int i = 0; i < count; i++)
            {
                lists[i] = await tasks[i]; //array out of range
            }

I'm facing extremely weird error. I have slightly simplified my code and provided the important part.

I'm creating a bunch of tasks, starting them, and then it fails instantly at 3rd loop. For some reason it uses old iterator that ended on 9, and increases it to 10, creating exception. I have no idea what to do, at the moment it looks like error of the environment.

Perro12
  • 21
  • 5
  • The value of count should be int count = unsortedLists.Count(). – jdweng Jan 10 '21 at 14:43
  • @jdweng it is equal. – Perro12 Jan 10 '21 at 14:45
  • Does this answer your question? [How to tell a lambda function to capture a copy instead of a reference in C#?](https://stackoverflow.com/questions/451779/how-to-tell-a-lambda-function-to-capture-a-copy-instead-of-a-reference-in-c) – Charlieface Jan 10 '21 at 14:45
  • 2
    You need to capture the loop variable. Alternatively `tasks = Enumerable.Range(0, 9).Select(i => Task.Run(() => {......}).ToArray(); await Task.WhenAll(tasks);` – Charlieface Jan 10 '21 at 14:46
  • @juharr above where you can't see it. I'm pretty sure i just don't know how to create tasks in a loop. – Perro12 Jan 10 '21 at 14:49
  • Please update the code extract to be [minimal and reproducible](https://stackoverflow.com/help/minimal-reproducible-example). – Connell.O'Donnell Jan 10 '21 at 14:50

1 Answers1

1

You should never use the task constructor. In this case, use Task.Run instead.

Your other problem is that the for loop in C# only defines a single loop variable, and lambdas close over variables, not values. This is why you're seeing an i that is 10.

The simplest solution is to do away with the for loops completely:

var tasks = Enumerable.Range(0, count)
    .Select(i => Task.Run(() =>
    {
      lists[i] = Sort(unsortedLists[i].ToArray()).ToList();
      return lists[i];
    }))
    .ToList();
var results = await Task.WhenAll(tasks);
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810