0

I want to create an array of Tasks, called listTask, with each element of listTask is a Task of type A, Task of type A is created by the function Task.WhenAll. then I do await Task.WhenAll(listTask) But the program does not perform the work in the listTask array. I set debug and those tasks were completed, I don't understand why

namespace Ding.LearningNewThings
{
    public class MultiChannelTask
    {
        public static async Task RunMiltipleChannel()
        {
            ConcurrentDictionary<int, Channel<Position>> _dataChannels = new ConcurrentDictionary<int, Channel<Position>>();

            var listPlace = Place.InitData();

            var numberOfPlace = listPlace.Count();

            for (int i = 0; i < listPlace.Count(); i++)
            {
                _dataChannels.TryAdd(i, Channel.CreateUnbounded<Position>());
            }

            Task[] listStationTask = new Task[numberOfPlace];

            for (var j = 0; j < numberOfPlace; j++)
            {
                var listTask = new Task[2];
                var placeOuter = listPlace[j];

                listTask[0] = Task.Run(async () =>
                {
                    int IndexOfPlace = j;
                    var place = new Place()
                    {
                        ID = placeOuter.ID,
                        Name = placeOuter.Name
                    };

                    Channel<Position> dataChannel;
                    var r = new Random();

                    if (_dataChannels.TryGetValue(IndexOfPlace, out dataChannel))
                    {
                        var position = new Position()
                        {
                            PlaceID = place.ID,
                            PlaceName = place.Name,
                            ID = r.Next(1, 100)
                        };

                        await dataChannel.Writer.WriteAsync(position);
                        Console.WriteLine($"Push postion ID {position.ID}, Place ID {position.PlaceID}");
                    }
                });

                listTask[1] = Task.Run(async () =>
                {
                    var IndexOfPlace = j;

                    Channel<Position> dataChannel;
                    var r = new Random();

                    if (_dataChannels.TryGetValue(IndexOfPlace, out dataChannel)) {

                        var position = await dataChannel.Reader.ReadAsync();

                        Console.WriteLine($"Get postion ID {position.ID}, Place ID {position.PlaceID}");
                    }
                });

                listStationTask[j] = Task.WhenAll(listTask);
            }

            await Task.WhenAll(listStationTask);
        }
    }

    public class Place
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public static List<Place> InitData()
        {
            var listData = new List<Place>();

            for (int i = 0; i < 10; i++)
            {
                var data = new Place()
                {
                    ID = i,
                    Name = $"Postion{i}",
                };

                listData.Add(data);
            }
            return listData;
        }
    }

    public class Position
    {
        public int ID { get; set; }
        public int PlaceID { get; set; }
        public string PlaceName { get; set; }
        public string Name { get; set; }

        public static List<Position> InitData()
        {
            var listData = new List<Position>();

            for (int i = 0; i < 10; i++)
            {
                var data = new Position()
                {
                    ID = i,
                    Name = $"Postion{i}"
                };

                listData.Add(data);
            }
            return listData;
        }
    }
}

I seem the task have had done ahead of intended. Sometimes it works, but I don't know why the job always completes without running in the list task code.

quanchinhong
  • 142
  • 3
  • 18
  • You should add some debugging to your code. I think (but I am not an expert) the `listTask[0] = Task.Run(async () =>....` will do something with the previous task that was in the `listTask[0]` before it ended. – Luuk Aug 14 '21 at 08:46
  • listTask[0] can do anything, It is ok. As long as it completes when I make the call await await Task.WhenAll(listStationTask); – quanchinhong Aug 14 '21 at 08:50
  • Related: [How to complete a Channel right way? How to use multiple channels?](https://stackoverflow.com/questions/68766755/how-to-complete-a-channel-right-way-how-to-use-multiple-channels) – Theodor Zoulias Aug 14 '21 at 08:57
  • no, I am also the author of that question. @TheodorZoulias – quanchinhong Aug 14 '21 at 09:01
  • Sorry, my English is bad. I want to create an array of Tasks, called listTask, with each element of listTask is a Task of type A, Task of type A is created by the function Task.WhenAll. then I do await Task.WhenAll(listTask) But the program does not perform the work in the listTask array. I set debug and those tasks were completed, I don't understand why @TheodorZoulias – quanchinhong Aug 14 '21 at 09:48
  • The one problem I see is using the for-loop variable `j` inside the worker methods of the tasks (`int IndexOfPlace = j;`). Some of the tasks probably not even start before your for-loop ends end the variable `j` already has a value of `numberOfPlace - 1`. So move `int IndexOfPlace = j;` out from the task body, before `listTask[0] = Task.Run(...)` – Steeeve Aug 14 '21 at 13:38
  • @Steeeve Can you give me a solution, I have no idea – quanchinhong Aug 14 '21 at 13:42
  • Simply move the first code-line `int IndexOfPlace = j;` in front of `listTask[0] = Task.Run(...)` and delete the line `var IndexOfPlace = j;` It's a pain in the ass typing code on my tablet, sorry... – Steeeve Aug 14 '21 at 13:49
  • It's like that made it work, I'm testing it more – quanchinhong Aug 14 '21 at 14:12
  • I put it in the Task.Run to avoid Closure, but Looks like that's the cause of the bug. lmao – quanchinhong Aug 14 '21 at 14:14
  • 1
    Did you also understand why? If not, see also [How can I capture the value of an outer variable inside a lambda expression?](https://stackoverflow.com/q/11049302/10318835) – Steeeve Aug 14 '21 at 14:27

0 Answers0