Feedback

Klasse zur parallelen Verarbeitung von Tasks

 RegexOptions.Compiled).Matches(src).Cast<Match>().Select(m => m.Groups[1].Value).Where(s => !string.IsNullOrEmpty(s)).Distinct();

1 Kommentar

  1. Das Muster, mehrere Tasks parallel auszuführen und auf alle zu warten, ist grundsätzlich weiterhin relevant. Der gezeigte Code spiegelt aber einen älteren Stil ohne moderne Asynchronitäts- und Parallelisierungs-Primitiven wider. Insbesondere wird eine eigene Warteschleife über Task.WhenAny geschrieben, statt vorhandene Bibliotheken und Sprachfeatures zu nutzen. Außerdem fehlen Cancellation-Unterstützung, saubere Fehlerbehandlung und Kontrolle über den Grad der Parallelität.

    [b]Analyse nach heutigen Kriterien:[/b]
    – [u]Performance[/u]: Die manuelle Schleife über Task.WhenAny mit Entfernen aus einer Liste funktioniert, ist aber unnötig kompliziert und erzeugt zusätzliche List-Allokationen. Task.WhenAll ist für „alle Tasks beenden“ effizienter und semantisch klarer.
    – [u]Memory-Allokationen[/u]: Die mutable Task-Liste und wiederholte Remove-Operationen erzeugen unnötige Allokationen und Reallokationen. Moderne APIs kommen ohne diese Struktur aus.
    – [u]Korrektheit[/u]: Exceptions einzelner Tasks werden nicht zentral behandelt. Fehler können unbemerkt bleiben oder erst sehr spät sichtbar werden.
    – [u]Robustheit[/u]: Es fehlt jegliche Cancellation-Unterstützung. In zeitgemäßen APIs gehört ein CancellationToken zwingend dazu.
    – [u]Thread-Safety[/u]: Der Ansatz ist grundsätzlich thread-safe, aber die manuelle Verwaltung der Task-Liste macht den Code fehleranfällig bei Erweiterungen.
    – [u]Cloud/Container[/u]: Blockierende Wait- oder Result-Zugriffe sind in Cloud-Workloads problematisch. Async/await ist der erwartete Standard.
    – [u]Standard-.NET-Ansatz[/u]: Task.WhenAll, Parallel.ForEachAsync, SemaphoreSlim oder Channels sind heute die bevorzugten Werkzeuge.

    [b]Modernisierte Variante (async/await, WhenAll, Cancellation):[/b]
    [code]
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    public static class ParallelTasks
    {
    public static Task WhenAll(Func[] taskFactories, CancellationToken cancellationToken = default)
    {
    if (taskFactories is null) throw new ArgumentNullException(nameof(taskFactories));

    var tasks = new Task[taskFactories.Length];
    for (int i = 0; i < taskFactories.Length; i++) tasks[i] = taskFactories[i](cancellationToken); return Task.WhenAll(tasks); } } [/code] [b]Warum das heute objektiv besser ist:[/b] - [u]Performance[/u]: Task.WhenAll nutzt die Laufzeit effizienter als manuelle Schleifen mit WhenAny. - [u]Robustheit[/u]: Fehler werden gesammelt propagiert, Cancellation ist sauber integrierbar. - [u]Memory-Allokationen[/u]: Keine dynamischen Listenmanipulationen. - [u]Cloud-Tauglichkeit[/u]: Async/await ohne Blockieren verhindert Threadpool-Starvation. [b]Security-Realitätscheck:[/b] Fehlende Cancellation oder Timeouts können in Server-Szenarien zu Ressourcenerschöpfung führen. Parallele Verarbeitung sollte immer begrenzt und kontrollierbar sein.