Séquencement des tâches et réentrée
Dans les scénarios où les tâches peuvent arriver plus rapidement qu'elles ne sont traitées et peuvent dépendre des résultats antérieurs, le séquençage des tâches devient crucial. Ce défi est aggravé lorsqu'une réentrée est requise.
Énoncé du problème
Un gestionnaire de commandes d'interface utilisateur peut traiter les commandes de manière synchrone ou asynchrone. Les commandes peuvent arriver à un rythme qui dépasse la vitesse de traitement, ce qui nécessite une mise en file d'attente et un traitement séquentiel. Le résultat de chaque nouvelle tâche peut dépendre de son prédécesseur. Bien que l'annulation soit exclue par souci de simplicité, la réentrée doit être prise en charge.
Approche initiale
Dans une application console de base, une classe AsyncOp gère le séquençage des tâches. Chaque tâche est traitée comme une continuation de la précédente, garantissant que les dépendances sont respectées. Cependant, lorsque la réentrée est introduite, la logique s'effondre.
Solution synchronisée
Pour résoudre ce problème, les tâches sont construites manuellement sans les planifier initialement. Au lieu de cela, « Task.Factory.StartNew » est utilisé pour exécuter les tâches de manière synchrone, les empêchant de s'exécuter jusqu'à ce que la tâche wrapper soit prête. Cela garantit que la séquence est maintenue.
Mise en œuvre du code
class AsyncOp<T> { Task<T> _pending = Task.FromResult(default(T)); public Task<T> CurrentTask => _pending; public Task<T> RunAsync(Func<Task<T>> handler, bool useSynchronizationContext = false) { var pending = _pending; var wrapper = async () => { var prevResult = await pending; Console.WriteLine($"\nprev task result: {prevResult}"); return await handler(); }; var task = new Task<Task<T>>(wrapper); var inner = task.Unwrap(); _pending = inner; task.RunSynchronously(useSynchronizationContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current); return inner; } }
Sortie mise à jour
Test #1... prev task result: 0 this task arg: 1000 prev task result: 1000 this task arg: 900 prev task result: 900 this task arg: 800 Press any key to continue to test #2... prev task result: 800 this task arg: 100 prev task result: 100 this task arg: 200
Extensions
Cette approche permet des améliorations supplémentaires telles que la sécurité des threads en implémentant un verrou sur protéger l’État partagé. De plus, une logique d'annulation/redémarrage peut être intégrée pour gérer les interruptions de tâches.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!