web-dev-qa-db-fra.com

Task.WhenAny - Que se passe-t-il avec les tâches en cours d'exécution restantes?

J'ai le code suivant:

List<Task<bool>> tasks = tasksQuery.ToList();
while (tasks.Any())
{
    Task<bool> completedTask = await Task.WhenAny(tasks);
    if (await completedTask)
        return true;

    tasks.Remove(completedTask);
}

Il lance des tâches en parallèle. Lorsque la première tâche terminée renvoie true, les méthodes retournent true.

Ma question est:

Que se passe-t-il avec toutes les tâches restantes qui ont été lancées et qui tournent probablement encore en arrière-plan?Est-ce la bonne approche pour exécuter un code asynchrone, parallèle et qui devrait revenir après la première condition se produit ou il vaut mieux les lancer un par un et attendre singulièrement?

Merci

23
Aleksander Bethke

Soit dit en passant, je lis juste Concurrence dans C # CookBook , par Stephen Cleary , et je peux me référer à certaines parties du livre ici, je suppose.

De Recette 2.5 - Discussion , nous avons

Une fois la première tâche terminée, envisagez d'annuler les tâches restantes. Si les autres tâches ne sont pas annulées mais ne sont également jamais attendues, elles sont alors abandonnées. Les tâches abandonnées s'exécuteront jusqu'à leur terme et leurs résultats seront ignorés . Toutes les exceptions à ces tâches abandonnées seront également ignorées.

Un autre antipattern pour Task.WhenAny gère les tâches à mesure qu'elles se terminent. Au début, il semble être une approche raisonnable de conserver une liste de tâches et de supprimer chaque tâche de la liste à mesure qu'elle se termine . Le problème avec cette approche est qu'elle s'exécute en temps O (N ^ 2), lorsqu'un algorithme O(N) existe).

En plus de cela, je pense que WhenAny est sûrement la bonne approche, pensez simplement à suivre Leonid approche en passant le même CancellationToken à chaque tâche et annulez-les après le premier retourne . Et même si, seulement au cas où le coût de ces opérations taxerait réellement le système.

13
heltonbiker