Avatar billede thepsypher Nybegynder
17. september 2010 - 12:33 Der er 14 kommentarer og
1 løsning

Upræcis timer og upræcise events...

Hej Eksperter....

Sidder og roder med en ret simpel applikation, som sender en "puls" ud på en serielport og sender en anden besked ud på en anden serielport. Pulsen er sat til et interval på 1 sekund, og beskeden på den anden port, kan forskydes fra 0 til 999 millisekunder (offset) af brugeren igennem GUI´en. F.eks. hvis den står på 0 kommer begge pulser samtidigt og hvis den står på 500 vil de komme forskudt.

Håber den forklaring gav mening...

Jeg tænkte at det var ret simpelt at lave med 2 timere, hvor den ene blev sat til ét sekund (interval=1000ms) og den sendte så pulsen ud og startede den anden timer, hvis interval var sat til den forskydelse brugeren havde sat (offsettet på 0 til 999 millisekunder). Den anden timer ville så sende beskeden ud på den anden serielport.

Det hele virker også ret godt, på nær at timeren ikke respekterer det interval man sætter den til i millisekunder.

Sættes den til 0, så venter den 15 sekunder.
Sættes den til 50, så venter den i 46 millisekunder.
Sættes den til 800, så venter den i 794 millisekunder.


Det virker som om at den springer i steps af 1/64 sekund ~ 15,63ms. Dette kan jo ikke accepteres, når brugeren skal kunne sætte den med 1 millisekunds nøjagtighed.

Har hørt om en Multimedia timer (som skulle have højere tidsopløsning), som jeg også har prøvet at benytte, men dette blev ikke meget bedre.

Dog skal det siges at Windows7 ser ud til at kunne håndtere det og er nede på millisekunds-præcision, men Windows XP inddeler stadig tiden i "pakker" af 15,63 sekunder!

Nogle gode forslag, tanker eller helt andre approaches?

Hilsen
Kasper
Avatar billede lasserasch Juniormester
17. september 2010 - 15:58 #1
Er bare med på en lytter....
Avatar billede Syska Mester
17. september 2010 - 16:11 #2
Lad være med at bruge .NET ... :-)

Jeg har aldrig læst om gode løsninger når vi er der nede og snakke milisekunder.

Problemet er sq nok måden hvorpå det hele er implmenteret i .NET. De fleste der laver real tids systemer, bruger ikke .NET.

Men jeg lytter også med ... men tvivler på der findes en løsning, som har 1 ms opløsning :-(((((

mvh
Avatar billede janus_007 Nybegynder
17. september 2010 - 18:54 #3
Hvad er "timeren" for en dims?

Hvordan kaldes den? Hvad har du wrappet? Hvad gør den?

Hvorfor taler du XP og W7 i et C#-forum? Er det fordi du vil udvikle din eget timersystem? Eller hur?
Avatar billede Syska Mester
17. september 2010 - 21:42 #4
Nu er det ikke mit spm janus, men ... mon ikke det er Timeren i .NET enten fra Threading eller WinForms ( Mener også der er en der )

Lyder ikke til at den er wrappet, på den måde han skriver.

Han snakker om Win7 og XP fordi der er forskel på hvordan de Timere i .NET opfører sig ... altså deres timing er bedre. Win7 gør det godt, mens XP indeler i 15.63 ms.

Igen ... han skal kunne lave delay på mellem 0 og 1000 ms på et eksisterende signal som kommer ind via en serial port og ud af en anden.

Har du læst hans spørgsmål eller hur? :-)
Avatar billede arne_v Ekspert
18. september 2010 - 03:43 #5
Windows og alle andre moderne generelle styre systemer fungerer på den måde at:
- en tråd kører på CPU'en indtil den frivilligt afgiver den eller den har kørt et bestemt antal millisekunder
- derefter udvælges der en ny tråd som er klar til at bruge CPU'en som så får CPU'en

Når en tråd sleeper, så afgiver den frivilligt CPU'en og den bliver først meldt klar til at få CPU'en igen efter T tid er gået.

Det betyder at en sleep vil vare mindst den angivne T, fordi den ikke er meldt klar inden, men at det sagtens kan tage længere tid end T, hvis der er andre tråde som også venter på CPU.

Jeg tvivler på at der er specielt stor forskel på XP og 7 - den forskel du har målt skyldes nok snarere forskel på hvad der kører på maskinen og evt. antal CPU'er (kerner) i maskinen.

Som tommelfinger regel skal du ikke forvente "gode" resultater under 50 millisekunders interval.

Skal du have noget bedre så vælg et real time OS til opgaven.

Og et andet sprog - garbage collection og real time er ikke nogen god kombo.
Avatar billede janus_007 Nybegynder
18. september 2010 - 12:13 #6
Jeg forstår spørgsmålet, men finder det ikke åbenlyst hvilke klasser der er brugt. Jojo.. vi kan jo gætte, der er mange der finder det fornøjeligt, men jeg arbejder bedst med problemområdet efter det er defineret ;)

Hvis vi gætter på at det er C#, så ja.. så vil timeren være upræcis af de årsager som Arne nævner.

Spørgsmålet er om det overhovedet skal laves på 2 timere, jeg tænker lidt.. gad vide... om man ikke kunne lave det på en 1 timer. Nu ved jeg heller ikke hvorfor det skal være en timer :) Man kunne måske lave det uden timers og med parallel.

Opret et kald til en metode.
I metoden starter du en rekursiv med parallelt kald.
Metoden sender et puls afsted og sleeper i det angivne tidsinterval. Lav en switch i metoden som skifter imellem den ene og anden port.


using System;
using System.Threading.Tasks;

namespace ParallelTiming
{
    class Program
    {
        static double lastTick;
        static int pulsCycle = 0;
        static void Main(string[] args)
        {
           
            StartPulsator(500);
            Console.ReadLine();

        }
        static void StartPulsator(int delayMilliseconds)
        {
            int i = 0;
            Console.WriteLine(string.Format("Puls cycle {0}", ++pulsCycle));
            Parallel.For(0, 2, p =>
                {

                    lastTick = DateTime.Now.Ticks;
                    SendPuls(500 * i++);
                });
        }

        static void SendPuls(int wait)
        {
            System.Threading.Thread.Sleep(wait);
            Console.WriteLine(string.Format("Sending Puls, {0}. Elapsed time {1}", wait, (DateTime.Now.Ticks - lastTick)/10000));
            if (wait > 0)
                StartPulsator(500);
        }
    }
}
Avatar billede arne_v Ekspert
18. september 2010 - 21:24 #7
For dem som gerne vil måle overhead with sleep så lavede jeg engang dette her program:

using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace E
{
    public static class Util
    {
        private static Socket s;
        static Util()
        {
            s =  new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.Bind(new IPEndPoint(IPAddress.Any, 12345));
        }
        public static void USleep(int us)
        {
            IList sl = new ArrayList();
            sl.Add(s);
            Socket.Select(sl, null, null, us);
        }
    }
    public class Program
    {
        public static void TestUSleep(int us)
        {
            DateTime t1 = DateTime.Now;
            for(int i = 0; i < 1000000/us; i++)
            {
                Util.USleep(us);
            }
            DateTime t2 = DateTime.Now;
            Console.WriteLine("USleep " + us + " microseconds, overhead factor=" + (t2 - t1).TotalSeconds);
        }
        public static void TestSleep(int ms)
        {
            DateTime t1 = DateTime.Now;
            for(int i = 0; i < 1000/ms; i++)
            {
                Thread.Sleep(ms);
            }
            DateTime t2 = DateTime.Now;
            Console.WriteLine("Sleep " + ms + " milliseconds, overhead factor=" + (t2 - t1).TotalSeconds);
        }
        public static void Main(string[] args)
        {
            TestUSleep(10);
            TestUSleep(50);
            TestUSleep(100);
            TestUSleep(500);
            TestUSleep(1000);
            TestSleep(1);
            TestSleep(5);
            TestSleep(10);
            TestSleep(50);
            TestSleep(100);
            TestSleep(500);
            TestSleep(1000);
        }
    }
}
Avatar billede thepsypher Nybegynder
21. september 2010 - 12:22 #8
Tusind tak for de fornuftige indlæg.

Jeg har både benyttet System.Timers.Timer og så prøvet denne "multimedia timer": http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx

I spørgsmålet om hvor præcist det er og kan blive og forskellen imellem winXP og Win7, så kan jeg oplyse at jeg prøvede at køre den samme applikation med forskellige tidsintervaller (for netop at se om den "puttede" dem ind på 15.63ms intervaller). Det var begge ret "rippede" OS´er, som ikke kørte andet. Tidstesten viste følgende:

Indstillet timer      WinXP        Win7
      1                15        1
    30                31        31
    50                46        51
    100              108      101
    200              202      201
    400              404      401
    800              809      801

De er alle kørt mange gange for at se afvigelser, gennemsnit, etc.
Så for mig at se viser det at WinXP inddeler tiden i de omtalte "intervaller" på cirka 15.63ms (+ mere variation end Win7) og at koden i Win7 er MEGET præcis.

Windows7´s timing resultater fra denne test er gode nok til min applikation og også de små afvigelser der kan opstå.

Men applikationen skal bare ikke være Win7 only, så arbejder mig hen imod at få den samme præcision og "opløsning" under XP.

Så essensen af mit problem ser stadig umiddelbart ud til at der i WinXP og med visse timere bliver sat en timer-præcision på 1/64-sekund, hvor imod i Win7 kan opnåes timer-præcision på 1ms.

Læser videre på jeres indlæg og tjekker jeres kode-eksempler ud...

Hilsen
Kasper
Avatar billede janus_007 Nybegynder
22. september 2010 - 22:29 #9
Problemet ligger formodentligt også i at du kører 2 timere på samme tråd! Hvor mange kerner har du?
Avatar billede thepsypher Nybegynder
22. september 2010 - 22:46 #10
Ok, det var et interessant indspark, det havde jeg ikke tænkt så meget på.
Jeg sidder desværre ikke på maskinen pt., men ud fra min hukommelse så er XP-maskinen måske nok en hurtigt single-core, hvorimod Win7-maskinen er nok en dual-core, men er dog i tvivl, så tjekker lige op på det imorgen...

Hilsen
Kasper
Avatar billede thepsypher Nybegynder
23. september 2010 - 12:05 #11
Nu har jeg tjekket og de 2 maskiner er følgende:

Win7-maskinen: Core2Duo T7300 @ 2GHz.

WinXP-maskinen: Pentium4 3GHz.

Så derfor er den maskine med dene høje præcision (Win7-maskinen) 2-kernet og maskinen med den lave og mere upræcise opløsning (WinXP-maskinen) 1-kernet, right?

Kan dette forsvare eller forklare forskellen?

Hilsen
Kasper
Avatar billede janus_007 Nybegynder
23. september 2010 - 21:04 #12
Ja jeg er overbevist om det er årsagen, på en single core skifter cpu'en imellem de forskellige tråde ca. hvert 20.ms og det er nok det du oplever. Det er kendt som time slicing.

Her er en udmærket intro, http://www.slideshare.net/rchakra/intro-to-net-threads
Avatar billede thepsypher Nybegynder
24. september 2010 - 12:32 #13
Har prøvet at køre en utility kaldet ClockRes: http://technet.microsoft.com/en-us/sysinternals/bb897568.aspx

Den viste noget interessant.

Hver gang jeg ikke kørte min applikation, så viste den følgende:

Win7-maskinen viste:

Maximum timer interval: 15.600ms
Minimum timer interval:  0.500ms
Current timer interval: 15.600ms

XP-maskinen viste:
Maximum timer interval: 15.625ms
Minimum timer interval:  1.000ms
Current timer interval: 15.625ms



Da jeg derimod kørte applikationen viste systemerne følgende:

Win7-maskinen viste:
Maximum timer interval: 15.600ms
Minimum timer interval:  0.500ms
Current timer interval:  1.000ms

XP-maskinen viste:
Maximum timer interval: 15.625ms
Minimum timer interval:  1.000ms
Current timer interval:  0.977ms

Ved ikke helt hvad det betyder eller hvordan det helt præcist skal forståes, men ved at det har relevans! ;-)

Betyder det at man i koden provokerer systemet til at benytte en højere opløsning af timeren end den ellers selv benytter?

Skal dog lige siges at jeg faktisk har fået den til at "makke ret", ved at re-programmere og simplificere koden. Jeg har dog ikke støt på fejl eller ting jeg har gjort fundamentalt anderledes, så er lidt forvirret over at jeg nu KAN opnå 1ms præcision og under WinXP.

Hvordan kan den egentlig vise at minimum interval for timeren er 1ms og at den så kører 0,977ms. Det giver jo ingen mening? Hvis det er rigtigt, kan den lille afvigelse mon forskyde noget over længere sigt?

Sorry for de mange tanker, kommentarer og spørgsmål, men det er jo også et omfattende og tungt emne! ;-)

Hilsen
Kasper
Avatar billede thepsypher Nybegynder
24. september 2010 - 14:59 #14
Har lige prøvet på en tredje maskine, som viste følgende i ClockRes applikationen:


Da min applikation IKKE kørte:

Maximum timer interval:  10.014ms
Minimum timer interval:  1.003ms
Current timer interval:  10.014ms

Da min applikation kørte:

Maximum timer interval: 10.014ms
Minimum timer interval:  1.003ms
Current timer interval:  1.003ms


Nogle som kan kaste mere lys over disse værdier? :-)

Hilsen
Kasper
Avatar billede thepsypher Nybegynder
01. marts 2011 - 00:20 #15
lukket
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester