2011-01-08 2 views
2

Je fais un stroboscope simple attaché à l'ordinateur. Je boucle Comme ça:Stroboscope C#, Thread.Sleep

double SleepTime = 1000/Hz; 

while() 
{ 
    BlinkAll(); 
    Thread.Sleep((int)SleepTime); 
} 

Mais cela est très inexact. Si Hz = 666 que SleepTime = 1,5 et (int) SleepTime = 1

cela signifie que la sortie je reçois 1000Hz pas 666Hz C'est grand diffrence.

Comment résoudre ce problème?

P.S.

Cet exemple n'est toujours pas précis. Il est préférable, mais pas bon en aucune façon:

double SleepTime = 1000/Hz; 
Thread.Sleep((int)SleepTime + 0.5) 
+5

'Threading.Sleep' est inexact jusqu'à 15ms, pour autant que je sache, et souvenez-vous. Ce n'est pas utilisable pour une telle tâche, même pas de près. – Bobby

+3

En fait, la précision n'est même pas proche de ça. Bien que vous puissiez spécifier une granularité de millisecondes, l'interruption utilisée a une fréquence inférieure, généralement de l'ordre de 10 millisecondes (différant entre différentes versions de système d'exploitation). Cela signifie que vous obtenez quelque chose comme 100 Hz plutôt que 1000 Hz. – Guffa

+1

Vous voudrez peut-être jeter un oeil à cette question: [Quelle est la précision de Thread.Sleep()] (http://stackoverflow.com/questions/1303667/how-accurate-is-thread-sleeptimespan) – Bobby

Répondre

2

Jetez un oeil à NtDelayExecution (ntdll.dll) ... il semble avoir une meilleure granularité (unités de 100 ns au lieu de 1 ms), même si je ne suis pas sûr combien cela aidera parce que je pense que les discussions sur Windows prennent chacune quelques millisecondes de tranche de temps.

+2

Oui, vous n'allez pas obtenir ce niveau de granularité ou de cohérence sur un non-RTOS. –

0

avez-vous essayé avec System.Timers.Timer? Je crois qu'il est beaucoup plus précis et accepte millisecondes afin que vous puissiez être tout à fait exact

+3

Vous frappez toujours un mur à environ 15 ms. –

0

Que diriez-vous quelque chose comme:

using System; 
using System.Threading; 
using System.Diagnostics; 

static class Program 
{ 
    static void Main() 
    { 
     const int Hz = 666; 
     var t0 = DateTime.Now; 
     int nCycles = 0; 
     var sw = Stopwatch.StartNew(); 
     while (sw.ElapsedMilliseconds < 10000) 
     { 
      ++nCycles; 
      var time = t0 + TimeSpan.FromMilliseconds(nCycles * 1000/Hz); 
      var ttw = (int)((time - DateTime.Now).TotalMilliseconds); 
      if (ttw >= 1) 
       Thread.Sleep(ttw); 
     } 
     Console.WriteLine(nCycles); 
    } 
} 
+3

Je le dis encore, 'Thread.Sleep()' [n'a pas la précision] (http://stackoverflow.com/questions/1303667/how-accurate-is-thread-sleeptimespan) pour 666Hz. Chaque fois que vous utilisez cette fonction, vous obtiendrez probablement quelque chose entre 10ms et 25ms. – Bobby