2009-07-01 6 views
10

Je dois faire une sorte de "timeout" ou de pause dans ma méthode pendant 10 secondes (10000 millisecondes), mais je ne suis pas sûr si ce qui suit fonctionnerait car je n'ai pas multi-threading.Mettre en pause une méthode pour l'ensemble Nombre de millisecondes

Thread.Sleep(10000); 

Je vais essayer d'utiliser ce code actuel, mais je vous serais reconnaissant si quelqu'un pourrait expliquer la meilleure façon et correcte de le faire, surtout si le code ci-dessus ne fonctionne pas correctement. Merci!

MISE À JOUR: Ce programme est en fait une application console qui, dans la fonction en question, effectue de nombreuses requêtes HTTPWeb sur un serveur, je souhaite donc les retarder pendant une durée spécifiée de quelques millisecondes. Ainsi, aucun rappel n'est requis - tout ce qui est nécessaire est une «pause inconditionnelle» - en gros, tout le reste s'arrête pendant 10 secondes et continue ensuite. Je suis heureux que C# considère toujours cela comme un thread, donc Thread.Sleep (...) fonctionnerait. Merci à tous!

+0

Est-ce une application Windows Forms? – Groo

+0

J'ai mis à jour le poste pour clarifier la nature de l'application. –

Répondre

12

Vous ne pouvez pas avoir multi -threading, mais vous exécutez toujours dans un thread: tout le code s'exécute dans un thread.

L'appel Thread.Sleep mettra en effet en pause le thread actuel. Voulez-vous vraiment qu'il fasse une pause inconditionnelle pendant 10 secondes, ou voulez-vous pouvoir être "réveillé" par quelque chose d'autre? Si vous utilisez uniquement un thread, appeler le Sleep pourrait bien être la meilleure solution, mais cela dépendra de la situation.

En particulier, si vous écrivez une application GUI vous ne pas veulent utiliser Thread.Sleep du thread d'interface utilisateur, sinon votre application entière ne répondra pendant 10 secondes. Si vous pouviez nous donner plus d'informations sur votre application, cela nous aiderait à mieux vous conseiller.

+1

Mon application est en fait une application de console qui fait une énorme quantité de requêtes HTTP à un serveur, donc je ne veux pas l'accabler et faire une pause entre les lots de 4 ou plus qui font déjà une pause automatiquement, mais sans un tel code. Oui j'espérais que C# reconnaisse toujours cela comme un fil donc merci! –

1

Oui, cela fonctionne très bien.

Vous n'avez pas besoin d'avoir plusieurs threads pour utiliser certaines des méthodes de la classe Thread. Vous avez toujours au moins un fil.

3

Cela mettra en effet en pause l'exécution du thread/méthode pendant 10 secondes. Voyez-vous un problème spécifique?

Notez que vous ne devriez pas Sleep le thread d'interface utilisateur - il serait préférable de faire un rappel à la place. Notez également qu'il existe d'autres façons de bloquer un thread qui permettent un accès plus simple pour le relancer (si vous trouvez qu'il est OK après 2s); tels que Monitor.Wait(obj, 10000) (permettant un autre thread Pulse si nécessaire pour le réveiller):

static void Main() { 
    object lockObj = new object(); 
    lock (lockObj) { 
     new Thread(GetInput).Start(lockObj); 
     Monitor.Wait(lockObj, 10000); 
    } 
    Console.WriteLine("Main exiting"); 
} 
static void GetInput(object state) { 
    Console.WriteLine("press return..."); 
    string s = Console.ReadLine(); 
    lock (state) { 
     Monitor.Pulse(state); 
    } 
    Console.WriteLine("GetInput exiting"); 
} 

Vous pouvez le faire avec Thread.Interrupt aussi, mais l'OMI qui est messier.

+0

Merci pour les conseils! –

0

Pour un délai d'attente, vous devez disposer d'un champ de classe isRunning boolean volatile statique. Lorsque le nouveau thread démarre, isRunning doit devenir true et à la fin doit devenir false.

Le thread principal doit avoir une méthode qui boucle pour isRunning pendant le délai que vous définissez. Lorsque le délai expire, vous devez implémenter la logique. Mais, n'utilisez jamais la méthode de thread d'abandon.

Une pause ...il n'y a pas de solution simple. Cela dépend de ce que vous faites dans le fil. Cependant, vous pouvez regarder Monitor.Wait.

1

Thread.Sleep est bien, et AFAIK la bonne façon. Même si vous n'êtes pas Multithread: Il y a toujours au moins un Thread, et si vous l'envoyez pour dormir, il dort.

Une autre (mauvaise) façon is a spinlock, quelque chose comme:

// Do never ever use this 
private void DoNothing(){ } 

private void KillCPU() 
{ 
    DateTime target = DateTime.Now.AddSeconds(10); 
    while(DateTime.Now < target) DoNothing(); 
    DoStuffAfterWaiting10Seconds(); 
} 

Ceci est malheureusement encore utilisé par les gens et alors qu'il arrêtera votre programme pendant 10 secondes, il fonctionnera à 100% d'utilisation du processeur (Eh bien, sur les systèmes multi-core c'est un noyau).

+0

Im plaçant à l'exemple de monopolisation de CPU - devra mettre cela dans mon livre comme une manière classique de remplir le CPU de quelqu'un! : D merci pour le conseil tho! –

+1

'while (DateTime.Now Groo

+0

Heureusement, je ne suis rien en termes de threading et tout ce qu'il y a de mieux - {} je comprends bien. : D –

2

Vous pouvez utiliser un thread séparé pour le faire:

ThreadPool.QueueUserWorkItem(
     delegate(object state) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("done"); 
     }); 

Mais, si cela est une application Windows Forms, vous devez invoquer le code après le délai du fil Gui (cet article par exemple: How to update the GUI from another thread in C#?).

[Éditer] Vous venez de voir votre mise à jour. Si c'est une application de console, alors cela fonctionnera. Mais si vous n'avez pas utilisé plusieurs threads jusqu'à présent, vous devez être conscient que ce code sera exécuté dans un thread différent, ce qui signifie que vous devrez faire attention aux problèmes de synchronisation des threads.

Si vous n'avez pas besoin de travailleurs de fond, tenez-vous-en à "garder les choses simples".

2

Voici une classe de pause qui fera une pause pendant les millisecondes désirées et ne consommera pas vos ressources CPU.

class PauseClass 
{ 
    //(C) Michael Roberg 
    //Please feel free to distribute this class but include my credentials. 

    System.Timers.Timer pauseTimer = null; 

    public void BreakPause() 
    { 
     if (pauseTimer != null) 
     { 
      pauseTimer.Stop(); 
      pauseTimer.Enabled = false; 
     }  
    } 

    public bool Pause(int miliseconds) 
    { 
     ThreadPriority CurrentPriority = Thread.CurrentThread.Priority; 

     if (miliseconds > 0) 
     { 
      Thread.CurrentThread.Priority = ThreadPriority.Lowest; 

      pauseTimer = new System.Timers.Timer(); 
      pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed); 

      pauseTimer.Interval = miliseconds; 
      pauseTimer.Enabled = true; 

      while (pauseTimer.Enabled) 
      { 
       Thread.Sleep(10); 
       Application.DoEvents(); 
       //pausThread.Sleep(1); 
      } 

      pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed); 
     } 

     Thread.CurrentThread.Priority = CurrentPriority; 

     return true; 
    } 

    private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     pauseTimer.Enabled = false; 
    } 
}