web-dev-qa-db-fra.com

Retarder puis exécuter la tâche

Question rapide, je veux attendre une seconde avant de lancer une tâche asynchrone sans valeur de retour.
Est-ce que c'est la bonne façon de le faire?

Task.Delay(1000)
    .ContinueWith(t => _mq.Send(message))
    .Start();

Qu'arrive-t-il aux exceptions?

40
David

Tout d'abord, Start() ne fonctionne que sur les (très rares) Tasks qui ont été créés à l'aide du constructeur Task (par exemple new Task(() => _mq.Send(message))). Dans tous les autres cas, il lèvera une exception, car Task est déjà démarré ou attend un autre Task.

Maintenant, la meilleure façon de le faire serait probablement de placer le code dans une méthode async distincte et d'utiliser await:

async Task SendWithDelay(Message message)
{
    await Task.Delay(1000);
    _mq.Send(message);
}

Si vous faites cela, toute exception de la méthode Send() se retrouvera dans le Task retourné.

Si vous ne voulez pas faire cela, utiliser ContinueWith() est une approche raisonnable. Dans ce cas, l'exception serait dans le Task renvoyé par ContinueWith().

En outre, selon le type de _mq, Envisagez d'utiliser SendAsync(), si quelque chose comme ça est disponible.

38
svick

Vous pouvez intercepter toute exception levée dans la tâche si vous attendez que la tâche se termine:

sachez que votre exception levée dans la tâche va être celle intérieure

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Task task = Task.Delay(1000)
                .ContinueWith(t => Program.throwsException());

            task.Wait();     
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception:" + ex.Message); // Outputs: Exception:One or more errors occurred.
            Console.WriteLine("Inner exception:" + ex.InnerException.Message); // Outputs: Exception:thrown
        }
        Console.ReadKey();

    }
    static void throwsException()
    {
        Console.WriteLine("Method started");
        throw new Exception("thrown");
    }
}
11
Attila

Vous pourrez observer toutes les exceptions si vous Wait pour la tâche.

Les exceptions non gérées qui sont levées par le code utilisateur qui s'exécute à l'intérieur d'une tâche sont propagées vers le thread de jointure, sauf dans certains scénarios décrits plus loin dans cette rubrique. Les exceptions sont propagées lorsque vous utilisez l'une des méthodes Task.Wait ou Task.Wait statiques ou d'instance et que vous les gérez en enfermant l'appel dans une instruction try-catch.

Extrait de Gestion des exceptions (bibliothèque parallèle de tâches)

Soyez prudent avec les horaires. Les tâches utilisent un planificateur et ne sont pas garanties de démarrer lorsque vous dites "allez". Votre code garantira au moins 1000ms de retard après l'avoir dit à Start mais il n'est pas garanti qu'il soit de 1000ms exactement.

0
Gusdor