.net - Threading.Timer problemer

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg bruger Threading.Timer, som:


new System.Threading.Timer(
            new System.Threading.TimerCallback(x=>
                file.Write(DateTime.Now.ToString())
            ), null, 0, 600000);


Og for eksempel starter den klokken 11:00:00, så kommer jeg ind i filen:


11:00:00

11:10:00

11:20:00

...

00:10:00

00:19:59

00:29:59



Hvorfor? fra en tid begynder det at gøre sådanne ting?
Jeg har prøvet andre timere, som Timers.Timer og Timer, den samme situation.
Det deprimerer mig.


EDIT: Løsning med korrekturlæsning, som blev lagt i tråden, hjalp ikke.
Hvad med win32 multimedia timer, kan det hjælpe?

Bedste reference


fordi timermekanismen ikke er ideel, er det nødvendigt med en del tid hver gang filen.Write (DateTime.Now.ToString () udføres. På den rette tid har du en forsinkelse på et sekund, så prøv at forlade det i en time, og jeg gætte du har 3 sekunders forsinkelse derefter.


Jeg er ikke sikker på, at når System.Threading.Timer kan kompensere dette ved at spore eksekveringstiden, bør du tjekke manualen for muligheder


Tag et kig på System.Timers.Timer klasse også.


Prøv også at bruge dette


class Timer
{
    private Stopwatch sw;
    private Thread executor;
    private long interval;

    public void Start(int intervalInMilliseconds)
    {
        interval = intervalInMilliseconds;
        sw = new Stopwatch();
        executor = new Thread(Run);
        executor.Start();
    }

    public void Run()
    {
        while (true)
        {
            sw.Start();
            Execute();
            sw.Stop();
            Thread.Sleep((int)(interval - sw.ElapsedMilliseconds));
            sw.Reset();
        }
    }


    public void Execute()
    {
        // Do your code here
    }

}

Andre referencer 1


Ja, timeren er underlagt at blive forgænget af andre vigtige opgaver. Ingen steder er det garanteret, at timeren vil udføre netop på det interval, du indstiller. Det er kun et omtrentligt interval, fordi Windows er et multitasking operativsystem. Hvis computeren har travlt med at gøre noget andet, vil det ikke være i stand til at betjene din timerbeskeder straks. Så meddelelserne bliver sat i en kø, som gør det muligt for dem at blive udskudt, indtil det kan gøre det.


Derfor skal du altid tjekke for en tidsværdi, der er lig med eller større end den tid du forventer. Det er garanteret at mindre tid aldrig vil være gået, men det er ikke garanteret at mere tid vundet ikke er gået. De øvrige timerimplementeringer er ikke forskellige.


Dokumentationen til timeren, der leveres af Windows API, går i detaljer: [8]



  En applikation bruger en timer til at planlægge en begivenhed for et vindue efter en bestemt tid er gået. Hver gang det angivne interval (eller timeout-værdi) for en timer forløber, meddeler systemet vinduet, der er forbundet med timeren. Fordi en timers nøjagtighed afhænger af systemets clockrate og hvor ofte applikationen henter meddelelser fra meddelelseskøen, er timeout-værdien kun omtrentlig.



Windows giver simpelthen ikke tidsmekanismerne så præcist. I 99 ud af 100 tilfælde er det simpelthen ikke relevant. For det 1 ud af 100 tilfælde har du brug for et operativsystem i realtid.

Andre referencer 2


Hvis du er villig til at ofre noget CPU-tid, kan du bruge multimedietimeren (check dette ud for en prøve C # implementering, som jeg brugte som grundlag for min egen komponent). [9]


Du vil opdage, at dens faktiske nøjagtighed er op til 1 ms, i modsætning til andre .NET-timer eller brugerdefinerede løsninger, der altid nødvendigvis vil stole på standard 15,625 ms Windows-timer.


Advarsler: (1) Jeg har kun kunnet oprette op til 2 forekomster af denne timer i samme AppDomain - i flere tilfælde har nogle af dem ikke hævet tick-arrangementerne overhovedet (eller efter et kort stykke tid) og ( 2) overvåge den øgede CPU-belastning og afgøre, om den ekstra nøjagtighed er værd.

Andre referencer 3


Her er mere præcis timeren for dig:


class AccurateTimer
{
    private TimerCallback \_Callback;
    private TimeSpan \_Period;
    private bool \_IsWorking = true;

    public void Stop()
    {
        \_IsWorking = false;
    }

    public AccurateTimer(TimerCallback callback, int period)
    {
        \_Period = TimeSpan.FromMilliseconds(period);
        \_Callback = callback;

        new Thread(ThreadMethod).Start();
    }

    private void ThreadMethod()
    {
        while (\_IsWorking)
        {
            var start = DateTime.Now;
            \_Callback.BeginInvoke(null, null, null);
            Thread.Sleep(\_Period - (DateTime.Now - start));
        }
    }
}


Anvendelse:


class Program
{
    static void Main(string[] args)
    {
        var timer = new AccurateTimer(x => Console.WriteLine(DateTime.Now.ToString("h:mm:ss.fff")), 3000);
        Console.ReadKey();
        timer.Stop();
    }
}


Produktion:


11:44:46.987
11:44:49.985
11:44:52.985
11:44:55.985
11:44:58.985
11:45:01.985


System.Threading.Timer:


class Program
{
    static void Main(string[] args)
    {
        new System.Threading.Timer(x => Console.WriteLine(DateTime.Now.ToString("h:mm:ss.fff")), null, 0, 3000);
        Console.ReadKey();
    }
}


Produktion:


11:50:22.042
11:50:25.040
11:50:28.051
11:50:31.065
11:50:34.073
11:50:37.083