Perro12
Perro12

Reputation: 21

Tasks fail to launch properly

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.

Upvotes: 0

Views: 57

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456577

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);

Upvotes: 1

Related Questions