Attendre quelques secondes sans bloquer L'exécution de L'interface utilisateur

je voudrais attendre quelques secondes entre deux instructions, mais sans bloquer l'exécution.

par exemple, Thread.Sleep(2000) ce n'est pas bon, parce qu'il bloque l'exécution.

l'idée est que j'appelle une méthode et puis j'attends X secondes (20 par exemple) en écoutant un événement venir. A la fin des 20 secondes je devrais faire une opération en fonction de ce qui s'est passé dans les 20 secondes.

41
demandé sur paqogomez 2014-03-04 01:53:56

7 réponses

je pense que ce que vous recherchez est une tâche.Retard. Cela ne bloque pas le thread comme le fait Sleep et cela signifie que vous pouvez le faire en utilisant un seul thread en utilisant le modèle de programmation async.

async Task PutTaskDelay()
{
    await Task.Delay(5000);
} 

private async void btnTaskDelay_Click(object sender, EventArgs e)
{
    await PutTaskDelay();
    MessageBox.Show("I am back");
}
66
répondu daniellepelley 2017-08-15 13:29:53

j'utilise:

private void WaitNSeconds(int segundos)
{
    if (segundos < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(segundos);
    while (DateTime.Now < _desired) {
         System.Windows.Forms.Application.DoEvents();
    }
}
20
répondu Omar 2017-08-15 13:31:28

c'est un bon cas pour l'utilisation d'un autre fil:

// Call some method
this.Method();

Task.Factory.StartNew(() =>
{
    Thread.Sleep(20000);

    // Do things here.
    // NOTE: You may need to invoke this to your main thread depending on what you're doing
});

le code ci-dessus attend .NET 4.0 ou au-dessus, sinon essayez:

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
    Thread.Sleep(20000);

    // Do things here
}));
9
répondu Matt 2014-03-03 21:59:44

la solution D'Omar est décente* si vous ne pouvez pas mettre à jour votre environnement à .NET 4.5 afin d'accéder à l'async et d'attendre les API. Cela dit, il y a ici un changement important qui devrait être fait afin d'éviter une mauvaise performance. Un léger délai doit être ajouté entre les appels à L'Application.DoEvents () afin d'éviter une utilisation excessive de CPU. En ajoutant

Thread.Sleep(1);

avant l'appel à Candidature.DoEvents (), vous pouvez ajouter un tel delay (1 milliseconde) et d'empêcher l'application d'utiliser tous les cycles cpu à sa disposition.

private void WaitNSeconds(int seconds)
{
    if (seconds < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(seconds);
    while (DateTime.Now < _desired) {
         Thread.Sleep(1);
         System.Windows.Forms.Application.DoEvents();
    }
}

*Voir la section https://blog.codinghorror.com/is-doevents-evil/ pour une discussion plus détaillée sur les écueils de l'utilisation de l'Application.DoEvents ().

8
répondu Nick Painter 2017-03-03 19:43:18

Si vous ne souhaitez pas bloquer les choses et aussi voulez pas utiliser le multi-threading, voici la solution pour vous: https://msdn.microsoft.com/en-us/library/system.timers.timer (v=V110).aspx

le Thread de L'interface utilisateur n'est pas bloqué et la minuterie attend 2 secondes avant de faire quelque chose.

voici le code provenant du lien ci-dessus:

        // Create a timer with a two second interval.
    aTimer = new System.Timers.Timer(2000);
    // Hook up the Elapsed event for the timer. 
    aTimer.Elapsed += OnTimedEvent;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program... ");
    Console.ReadLine();
    Console.WriteLine("Terminating the application...");
3
répondu Daan 2015-03-28 18:47:20

je vous déconseille vraiment d'utiliser Thread.Sleep(2000) , pour plusieurs raisons (quelques-unes sont décrites ici ), mais surtout parce que ce n'est pas utile quand il s'agit de débogage/test.

je recommande d'utiliser un C# Timer au lieu de Thread.Sleep() . Timers vous permettent d'effectuer des méthodes fréquemment (si nécessaire) et sont beaucoup plus facile à utiliser dans les essais! Il y a un très bel exemple d'utilisation d'une minuterie juste derrière le hyperlink - mettez juste votre logique "ce qui se passe après 2 secondes" dans la méthode Timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); .

2
répondu Matthias R. 2017-05-23 11:47:05

regardez dans la classe System.Threading.Timer . Je pense que c'est ce que vous cherchez.

l'exemple de code sur MSDN semble montrer que cette classe fait très similaire à ce que vous essayez de faire (vérifier l'état après un certain temps).

0
répondu LB2 2014-03-03 22:09:16