web-dev-qa-db-fra.com

Comment puis-je effectuer un court délai en C # sans utiliser le sommeil?

Je suis incroyablement novice en programmation et je pense avoir appris suffisamment bien jusqu'à présent, mais je ne comprends toujours pas l'idée de retarder le délai que je souhaite. Je travaille sur une sorte de "jeu" de test utilisant une application Windows Forms qui implique un système de combat. Dans ce document, je souhaite créer un NPC exécutant une action toutes les deux secondes. Le problème est que je veux aussi permettre au joueur d’interagir entre les attaques. Thread.sleep ne semble vraiment pas fonctionner pour moi, non seulement parce que je ne sais pas multithread, mais chaque fois que j'essaie de l'exécuter, dites, comme ceci: 

 textBox1.Text += "\r\nThread Sleeps!";
 System.Threading.Thread.Sleep(4000);
 textBox1.Text += "\r\nThread awakens!";

Il semble insister pour dormir d'abord, puis pour imprimer les deux lignes. 

Je pense que c'est tout ce que je peux dire pour le moment, mais si cela reste trop vague ou trop verbeux, n'hésitez pas à me le dire. 

En bref, en C #, je veux faire quelque chose de retard avant d’exécuter, tout en autorisant les interactions de l’utilisateur.

21
user2706003

Si vous utilisez .NET 4.5, vous pouvez utiliser le nouveau framework async/wait pour mettre en veille sans verrouiller le thread. 

Comment ça marche, c'est que vous marquez la fonction nécessitant des opérations asynchrones, avec le mot clé async. Ceci est juste un indice pour le compilateur. Ensuite, vous utilisez le mot clé await sur la ligne où vous souhaitez que votre code s'exécute de manière asynchrone. Votre programme attendra sans verrouiller le thread ni l'interface utilisateur. La méthode que vous appelez (sur la ligne d'attente) doit également être marquée avec un mot clé async et porte généralement le nom Async, comme dans ImportFilesAsync.

Ce que vous devez faire dans votre exemple est:

  1. Assurez-vous que votre programme a .Net Framework 4.5 comme Framework cible
  2. Marquez votre fonction qui doit dormir avec le mot clé async (voir l'exemple ci-dessous)
  3. Ajoutez using System.Threading.Tasks; à votre code.

Votre code est maintenant prêt à utiliser la méthode Task.Delay au lieu de la méthode System.Threading.Thread.Sleep (il est possible d'utiliser await sur Task.Delay car Task.Delay est marqué avec async dans sa définition).

private async void button1_Click(object sender, EventArgs e)
{
    textBox1.Text += "\r\nThread Sleeps!";
    await Task.Delay(3000);
    textBox1.Text += "\r\nThread awakens!";
}

Ici, vous pouvez en savoir plus sur Task.Delay et Await .

53
Ohlin

Désolé de réveiller une vieille question comme celle-ci. Mais je pense que ce que l'auteur original voulait en guise de réponse était:

Vous devez obliger votre programme à mettre à jour le graphique après avoir modifié la zone de texte1. Vous pouvez le faire en appelant Update();

textBox1.Text += "\r\nThread Sleeps!";
textBox1.Update();
System.Threading.Thread.Sleep(4000);
textBox1.Text += "\r\nThread awakens!";
textBox1.Update();

Normalement, cela se fera automatiquement quand le fil est terminé . Ex, vous appuyez sur un bouton, le texte est modifié, le fil meurt, puis .Update() est déclenché et vous voyez les changements ..__ pas un expert, donc je ne peux pas vraiment vous dire quand il est viré, mais c'est quelque chose de semblable à cela de toute façon.)

Dans ce cas, vous apportez une modification, mettez le fil en pause, puis vous modifiez à nouveau le texte. Lorsque le fil meurt, la fonction .Update() est déclenchée. Cela a pour conséquence que vous ne voyez que la dernière modification apportée au texte.

Vous rencontreriez le même problème si vous aviez une longue exécution entre les modifications de texte.

4
Tomas Frid

En ajoutant using System.Timers; à votre programme, vous pouvez utiliser cette fonction:

private static void delay(int Time_delay)
{
   int i=0;
  //  ameTir = new System.Timers.Timer();
    _delayTimer = new System.Timers.Timer();
    _delayTimer.Interval = Time_delay;
    _delayTimer.AutoReset = false; //so that it only calls the method once
    _delayTimer.Elapsed += (s, args) => i = 1;
    _delayTimer.Start();
    while (i == 0) { };
}

Le délai est une fonction et peut être utilisé comme:

delay(5000);
2
user8413784

Vous pouvez probablement utiliser des minuteries: http://msdn.Microsoft.com/en-us/library/system.timers.timer.aspx

Les minuteries peuvent vous fournir une précision allant jusqu'à 1 milliseconde. En fonction de l'intervalle de tick, un événement sera généré. Faites vos affaires à l'intérieur de l'événement tick.

1
Abhishek Shetty
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();
    }
}
0
Khalid