Maison > développement back-end > C++ > Comment AsyncOp peut-il gérer efficacement le séquençage des tâches et la réentrée dans les environnements multithread ?

Comment AsyncOp peut-il gérer efficacement le séquençage des tâches et la réentrée dans les environnements multithread ?

Linda Hamilton
Libérer: 2025-01-04 20:13:49
original
251 Les gens l'ont consulté

How Can AsyncOp Efficiently Manage Task Sequencing and Re-Entrancy in Multithreaded Environments?

Séquençage des tâches et réentrée : gestion des commandes séquentielles dans un environnement multithread

Dans les applications logicielles du monde réel, il est courant de rencontrer des scénarios où les tâches sont traitées séquentiellement et leur ordre d’exécution est critique. Le séquençage des tâches devient encore plus complexe lorsque les tâches peuvent arriver plus rapidement qu'elles ne peuvent être traitées et qu'elles sont réentrantes, ce qui signifie qu'elles peuvent s'exécuter simultanément en elles-mêmes.

Considérez le scénario suivant :

  1. Une tâche de gestionnaire de commandes de l'interface utilisateur peut être exécutée de manière synchrone ou asynchrone.
  2. Les commandes peuvent arriver à un rythme plus rapide qu'elles ne le sont. traité.
  3. Si une tâche en attente existe déjà pour une commande, la nouvelle tâche du gestionnaire de commandes doit être mise en file d'attente et exécutée séquentiellement.
  4. Le résultat de chaque nouvelle tâche peut dépendre du résultat de la précédente. tâche.

Traditionnellement, le problème de synchronisation ou d'asynchronisation peut être résolu en utilisant la méthode Task.Factory.StartNew avec le Paramètre TaskScheduler.FromCurrentSynchronizationContext() pour forcer l’exécution asynchrone. Cependant, cette approche n'est peut-être pas idéale si les gestionnaires de commandes sont conçus pour s'exécuter de manière synchrone en interne.

Pour relever ce défi, une classe personnalisée appelée AsyncOp peut être implémentée. AsyncOp gère le séquençage des tâches et les exigences de réentrée. Voici une version mise à jour de la classe AsyncOp avec des fonctionnalités supplémentaires :

class AsyncOp<T>
{
    private Task<T> _pending = Task.FromResult(default(T));
    private readonly object _lock = new object();

    public Task<T> CurrentTask => _pending;

    public Task<T> RunAsync(Func<Task<T>> handler, bool useSynchronizationContext = false)
    {
        Task<Task<T>> task = null;

        lock (_lock)
        {
            var pending = _pending;
            Task<T> wrapper = async () =>
            {
                // Await the previous task
                T prevResult = await pending;
                Console.WriteLine("\nPrevious task result: " + prevResult);

                // Start and await the handler
                return await handler();
            };

            task = new Task<Task<T>>(wrapper);
            var inner = task.Unwrap();
            _pending = inner;
        }

        task.RunSynchronously(useSynchronizationContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current);

        return inner;
    }

    public async Task HandleCancelAsync()
    {
        Task pendingCopy = null;

        lock (_lock)
        {
            pendingCopy = _pending;
        }

        // Cancel previous tasks as long as they are not the latest (current) task
        if (pendingCopy != CurrentTask && pendingCopy != null) await ((Task)pendingCopy).ContinueWith(t => t.Dispose());
    }

    public async Task HandleRestartAsync()
    {
        Task pendingCopy = null;

        lock (_lock)
        {
            pendingCopy = _pending;
            if (pendingCopy.IsCompleted && pendingCopy != null) _pending = Task.FromResult(default(T));
        }
    }
}
Copier après la connexion

Cette version mise à jour fournit les améliorations suivantes :

  • Réentrée : AsyncOp prend désormais en charge la réentrée en autorisant les tâches.
  • Sécurité des threads : Un verrou est utilisé pour protéger le champ _ending.
  • Annuler/Redémarrer : Nouveau Méthodes HandleCancelAsync et HandleRestartAsync vous permettent d'annuler ou de redémarrer la séquence de tâches avec élégance.

À l'aide de cette classe AsyncOp mise à jour, l'exemple de code fourni dans la question peut être réécrit comme suit :

using System;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var asyncOp = new AsyncOp<int>();

            Func<int, Task<int>> handleAsync = async (arg) =>
            {
                Console.WriteLine("This task arg: " + arg);

                // Delay the execution
                await Task.Delay(arg); 

                return await Task.FromResult(arg); 
            };

            Console.WriteLine("Test #1...");
            asyncOp.RunAsync(() => handleAsync(1000));
            asyncOp.RunAsync(() => handleAsync(900));
            asyncOp.RunAsync(() => handleAsync(800));
            await asyncOp.CurrentTask;

            Console.WriteLine("\nPress any key to continue to test #2...");
            Console.ReadLine();

            asyncOp.RunAsync(() =>
            {
                var handle100Task = handleAsync(100);
                asyncOp.RunAsync(() => handleAsync(200), true);
                return handle100Task;
            });

            await asyncOp.CurrentTask;
            Console.WriteLine("\nPress any key to exit...");
            Console.ReadKey();
        }
    }
}
Copier après la connexion

Dans cette version mise à jour, la tâche handleAsync est forcée de s'exécuter de manière asynchrone à l'aide de la méthode Task.Delay pour démontrer les capacités de réentrance de AsyncOp.

Cette solution fournit un moyen robuste et efficace de gérer le séquençage et la réentrée des tâches, garantissant que les commandes sont exécutées dans l'ordre souhaité, quelle que soit la vitesse à laquelle elles arrivent.

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal