Laden...

Wie Task.WhenAll für eine Liste implementieren, sodass man die Liste nachher bearbeiten kann?

Erstellt von BlackMatrix vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.064 Views
B
BlackMatrix Themenstarter:in
218 Beiträge seit 2012
vor 7 Jahren
Wie Task.WhenAll für eine Liste implementieren, sodass man die Liste nachher bearbeiten kann?

Hallo,

mir fallen zwar ein paar Möglichkeiten ein wie man das Problem lösen könnte, aber irgendwie bin ich noch nicht auf eine Best practice Lösung im Internet gestoßen, obwohl ich das eigentlich als etwas Fundamentales erachte.
Task.WhenAll bietet nur Überladungen für IEnumerable<Task> bzw. feste Arrays ala Task[]
Wie würdest ihr Task.WhenAll für eine Liste implementieren, sodass man nachträglich Elemente hinzufügen bzw. entfernen kann?

Folgendes Codebeispiel mit erwartetem Debug.Assert (der so wie er jetzt dort steht, fehlschlägt)


        private async void Click()
        {
            var tasks = new ConcurrentBag<Task>(Enumerable.Range(0, 10).Select(i => Task.Delay(i*1000)));

            var thread = new Thread(() =>
            {
                Thread.Sleep(1000);
                tasks.Add(Task.Delay(30000));
            });
            thread.Start();

            var sw = Stopwatch.StartNew();

            await Task.WhenAll(tasks);

            sw.Stop();

            Debug.Assert(sw.ElapsedMilliseconds > 30000);
        }

Ich freue mich auf eure Ideen 😃

D
985 Beiträge seit 2014
vor 7 Jahren

Wenn du einen neuen Task hinzufügst, dann befindet sich dieser nicht in dem IEnumerable<Task>, auf den du Task.WhenAll loslässt.

Sieht man, wenn man einen Blick in den Source von ConcurrentBag wirft. Von daher ist das Verhalten also absolut nachvollziehbar.

Man muss also bei jeder Änderung der Liste einen neuen Task.WaitAll aufrufen, damit man auch auf das Ende von allen Tasks wartet.