Maison >développement back-end >C++ >Comment garantir l'exécution séquentielle des tâches et la réentrée dans les opérations asynchrones ?

Comment garantir l'exécution séquentielle des tâches et la réentrée dans les opérations asynchrones ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-30 12:17:10897parcourir

How to Ensure Sequential Task Execution and Re-entrancy in Asynchronous Operations?

Séquençage des tâches et réentrée

Problème :

Envisagez un scénario dans lequel les tâches peuvent être exécuté de manière synchrone ou asynchrone. Si une nouvelle tâche est reçue alors qu'une tâche précédente est toujours en attente, la nouvelle tâche doit être mise en file d'attente et exécutée séquentiellement. De plus, le résultat de chaque tâche peut dépendre du résultat de la tâche précédente. Le défi est de mettre en œuvre cette logique tout en prenant en charge la réentrée, où une tâche peut être exécutée plusieurs fois de suite.

Solution :

Pour imposer l'exécution séquentielle des tâches et pour éviter de rompre la logique due à la réentrée, il est nécessaire de construire manuellement des tâches à l'aide de l'outil Task constructeur et démarrez-les plus tard. La méthode Task.Unwrap() peut être utilisée pour obtenir la tâche réelle qui sera exécutée.

La méthode AsyncOp La classe ci-dessous implémente cette approche :

class AsyncOp<T>
{
    Task<T> _pending = Task.FromResult(default(T));

    public Task<T> CurrentTask { get { return _pending; } }

    public Task<T> RunAsync(Func<Task<T>> handler, bool useSynchronizationContext = false)
    {
        var pending = _pending;
        Func<Task<T>> wrapper = async () =>
        {
            // await the prev task
            var prevResult = await pending;
            Console.WriteLine("\nprev task result:  " + prevResult);
            // start and await the handler
            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;
    }
}

En utilisant cette classe AsyncOp modifiée, l'exécution séquentielle des tâches et la réentrée sont assurées. Le code modifié produit le résultat souhaité :

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

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!

Déclaration:
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