web-dev-qa-db-fra.com

Task.Wait (int) arrête-t-il la tâche si le délai expire sans que la tâche se termine?

J'ai une tâche et je m'attends à ce qu'elle prenne moins d'une seconde pour s'exécuter, mais si cela prend plus de quelques secondes, je veux annuler la tâche.

Par exemple:

Task t = new Task(() =>
        {
            while (true)
            {
                Thread.Sleep(500);
            }
        });
t.Start();
t.Wait(3000);

Notez qu'après 3000 millisecondes, l'attente expire. La tâche a-t-elle été annulée lorsque le délai a expiré ou la tâche est-elle toujours en cours d'exécution?

32
Paul Mendoza

Si vous souhaitez annuler un Task, vous devez saisir un CancellationToken lorsque vous créez la tâche. Cela vous permettra d'annuler le Task de l'extérieur. Vous pouvez lier l'annulation à une minuterie si vous le souhaitez.

Pour créer une tâche avec un jeton d'annulation, consultez cet exemple:

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var t = Task.Factory.StartNew(() => {
    // do some work
    if (token.IsCancellationRequested) {
        // Clean up as needed here ....
    }
    token.ThrowIfCancellationRequested();
}, token);

Pour annuler le Task appelez Cancel() sur le tokenSource.

16
Brian Rasmussen

Task.Wait() attend jusqu'à période spécifiée pour l'achèvement de la tâche et retourne si la tâche s'est terminée dans le laps de temps spécifié (ou antérieur) ou ne pas. La tâche elle-même n'est pas modifiée et ne repose pas sur l'attente.

Lire Nice series: Parallelism in .NET , Parallelism in .NET - Part 10, Cancellation in PLINQ and the Parallel class by Reed Copsey

Et: .NET 4 Cancellation Framework / Programmation parallèle: Annulation de tâche

Vérifiez le code suivant:

var cts = new CancellationTokenSource();

var newTask = Task.Factory.StartNew(state =>
                           {
                              var token = (CancellationToken)state;
                              while (!token.IsCancellationRequested)
                              {
                              }
                              token.ThrowIfCancellationRequested();
                           }, cts.Token, cts.Token);


if (!newTask.Wait(3000, cts.Token)) cts.Cancel();
52
Nick Martyshchenko

La tâche est toujours en cours d'exécution jusqu'à ce que vous lui disiez explicitement d'arrêter ou que votre boucle se termine (ce qui ne se produira jamais).

Vous pouvez vérifier la valeur de retour de Wait pour voir ceci:

(à partir de http://msdn.Microsoft.com/en-us/library/dd235606.aspx ) Valeur de retour

Type: System.Boolean true si la tâche a terminé son exécution dans le délai imparti; sinon, faux.

7
vdoogs

La tâche a-t-elle été annulée lorsque le délai a expiré ou la tâche est-elle toujours en cours d'exécution?

Non et oui.

Le délai est passé à Task.Wait est pour le Wait, pas pour la tâche.

6
Richard

Si votre tâche appelle une méthode synchrone qui effectue tout type d'E/S ou toute autre action non spécifiée qui prend du temps, il n'existe aucun moyen général de "l'annuler".

Selon la façon dont vous essayez de "l'annuler", l'une des situations suivantes peut se produire:

  • L'opération est en fait annulée et la ressource sur laquelle elle fonctionne est dans un état stable (vous avez eu de la chance!)
  • L'opération est en fait annulée et la ressource sur laquelle elle travaille est dans un état incohérent (pouvant entraîner toutes sortes de problèmes plus tard)
  • L'opération continue et interfère potentiellement avec tout ce que fait votre autre code (ce qui peut entraîner toutes sortes de problèmes plus tard)
  • L'opération échoue ou provoque le blocage de votre processus.
  • Vous ne savez pas ce qui se passe, car il n'est pas documenté

Il existe des scénarios valides où vous pouvez et devez probablement annuler une tâche en utilisant l'une des méthodes génériques décrites dans les autres réponses. Mais si vous êtes ici parce que vous voulez interrompre une méthode synchrone spécifique, mieux vaut voir la documentation de cette méthode pour savoir s'il existe un moyen de l'interrompre, si elle a un paramètre "timeout", ou s'il y a une variation interruptible de celui-ci.

0
Florian Winter