Die Berechnung Anzahl der Sekunden zwischen zwei Zeitpunkten, in Cocoa, auch wenn Systemuhr auf halbem Weg geändert hat

StackOverflow https://stackoverflow.com/questions/1627764

Frage

Ich schreibe ein Cocoa O X (Leopard 10.5 und höher) Endbenutzer-Programm, das Zeitstempel ist mit Statistiken zu berechnen, wie lange etwas auf dem Bildschirm angezeigt wird. Die Zeit wird berechnet periodisch während das Programm eine Wiederholung NSTimer Läufe mit. [NSDate date] wird verwendet, Zeitstempel zu erfassen, Start und Fertig . Berechnung der Differenz zwischen den beiden Daten in Sekunden ist trivial.

Ein Problem tritt auf, wenn ein Endbenutzer oder ntp den Systemtakt ändert. [NSDate date] beruht auf der Systemtakt, also wenn es sich verändert hat, die Fertig Variable wird schräg in Bezug auf die Start sein , vermasselt signifikant die Zeitberechnung. Meine Frage:

1. Wie kann ich genau die Zeit zwischen dem Start und Fertig stellen in Sekunden berechnen, auch wenn der Systemtakt wird auf halben Weg geändert?

Ich denke, dass ich einen sich nicht ändernden Referenzzeitpunkt benötigen, so kann ich berechnen, wie viele Sekunden seither vergangen ist. Zum Beispiel der Systemverfügbarkeit. 10,6 hat - (NSTimeInterval)systemUptime, Teil NSProcessInfo, die Systembetriebszeit bietet. Dies wird jedoch nicht wie mein app in 10.5 arbeiten muß.

Ich habe versucht, einen Zeitzähler zu schaffen NSTimer verwenden, aber das ist nicht korrekt. NSTimer hat mehrere verschiedenen Lauf Modi und nur einen nach dem anderen ausgeführt werden kann. NSTimer (Standardeinstellung) wird gesetzt in die default Run-Modus. Wenn ein Benutzer startet für eine ausreichend lange Zeit, um die UI zu manipulieren, wird diese Eingabe NSEventTrackingRunLoopMode und überspringt den default Run-Modus, was zu NSTimer Zündungen seines übersprungen führen kann, so dass es eine ungenaue Weise Sekunden zu zählen.

ich auch gedacht habe über einen separaten Thread (NSRunLoop) Erzeugen eines NSTimer zweiten Zähler zu laufen, ist es weg von UI-Interaktionen zu halten. Aber ich bin sehr neu für Multi-Threading und ich möchte bleiben weg von, wenn möglich. Auch ich bin nicht sicher, ob dies würde genau in dem Fall arbeitet die CPU durch eine andere Anwendung (Photoshop-Rendering ein großes Bildes, etc ...) gebunden werden, so dass mein NSRunLoop für lange genug, um Chaos auf Eis gelegt werden, bis sein NSTimer.

Ich schätze jede mögliche Hilfe. :)

War es hilfreich?

Lösung 3

dachte ich, einen Ausweg, dies zu tun, um die UpTime () C-Funktion, in <CoreServices/CoreServices.h> zur Verfügung gestellt. Dies gibt Absolute Time (CPU-spezifisch), die leicht in Dauer Zeitumgerechnet werden kann (Millisekunden oder Nanosekunden). Details hier: http://www.meandmark.com/timingpart1.html (schauen Sie unter Teil 3 für UpTime)

Ich konnte nicht mach_absolute_time() richtig zu arbeiten, wahrscheinlich aufgrund meiner Mangel an Wissen über sie, und nicht in der Lage, viel Dokumentation auf dem Internet über sie zu finden. Es scheint, die gleiche Zeit wie UpTime() zu greifen, aber es in einem doppelten Umwandlung ließ mich sprachlos.

[[NSApp currentEvent] timestamp] haben funktioniert, aber nur, wenn die Anwendung empfängt NSEvents. Wenn die Anwendung in den Vordergrund gingen, würde es keine Ereignisse empfangen und [[NSApp currentEvent] timestamp] würde einfach weiterhin die gleichen alten Zeitstempel immer wieder in einem NSTimer Brennverfahren zurückzukehren, bis der Endbenutzer wieder mit der App interagieren entschieden.

Vielen Dank für Ihre Hilfe Marc und Mike! Sie beide schickte mich auf jeden Fall in die richtige Richtung, um die Antwort führt. :)

Andere Tipps

Je nachdem, was diesen Code fährt, haben Sie zwei Möglichkeiten:

  • Für absolute Präzision, verwenden Sie mach_absolute_time() . Es wird das Zeitintervall genau zwischen den Punkten geben, an dem Sie die Funktion aufgerufen.
  • Aber in einer GUI-Anwendung, ist dies oft sogar unerwünscht. Stattdessen möchten Sie die Zeitdifferenz zwischen den Ereignisse , die Ihre Dauer gestartet und beendet. Wenn ja, vergleichen [[NSApp currentEvent] timestamp]

Okay, so ist dies ein weit hergeholt, aber man könnte versuchen, etwas ein bisschen wie NSSystemClockDidChangeNotification in Snow Leopard zu implementieren.

Also bei mir tragen hier, denn dies ist eine seltsame Idee ist und ist auf jeden Fall nicht derterministic. Aber was, wenn Sie hatte einen Watchdog-Faden durch die Dauer des Programms ausgeführt wird? Dieser Thread würde, alle n Sekunden, lesen Sie die Systemzeit und speichern. Aus Gründen der Argumentation, machen sie es nur 5 Sekunden machen. Also alle 5 Sekunden, vergleicht er die vorherige Lektüre der aktuellen Systemzeit. Wenn es ein „groß genug“ Unterschied ist ( „groß genug“ müßte auf jeden Fall größer als 5, aber nicht zu viel größer, für den Nicht-Determinismus der Prozessplanung und Priorisierung von Threads zu berücksichtigen), Post eine Benachrichtigung, dass eine signifikante Zeitänderung wurde. Sie müßten mit fuzzing den Wert spielen, um die „groß genug“ darstellt (oder klein genug, wenn die Uhr zu einem frühen Zeitpunkt zurückgesetzt wurde) für Ihre Genauigkeit benötigt.

Ich weiß, diese Art von Hacky ist, aber sofern keine andere Lösung, was denken Sie? Könnte das, oder so ähnlich, lösen Ihr Problem?

Bearbeiten

Okay, so modifiziert Sie Ihre ursprüngliche Frage zu sagen, dass Sie lieber nicht einen Watchdog-Thread verwenden, da Sie Multithreading neu sind. Ich verstehe die Angst vor etwas etwas fortgeschritteneren tun, als Sie sind komfortabel mit, aber dies könnte die einzige Lösung am Ende. In diesem Fall könnten Sie ein bisschen Lesen zu tun haben. =)

Und ja, ich weiß, dass etwas wie Photoshop den Mist aus dem Prozessor pegging ein Problem ist. Eine weitere (noch komplizierter) Lösung sein würde, anstatt einen Watchdog Thread von , hat eine separate Watchdog Prozess , die höchste Priorität hat, so dass es ein bisschen mehr immun gegen Prozessor pegging. Aber auch hier ist das wirklich kompliziert zu werden.

Endgültiges Bearbeiten

Ich werde alle meine andere Ideen über der Vollständigkeit halber verlassen, aber es scheint, dass die Systemverfügbarkeit verwendet, wird auch ein gültiger Weg, damit umzugehen. Da [[NSProcessInfo processInfo] systemUptime] funktioniert nur in 10.6+, können Sie einfach mach_absolute_time() nennen. Um Zugriff auf diese Funktion, #include <mach/mach_time.h> einfach. Das sollte der gleiche Wert, wie er durch NSProcessInfo zurückgegeben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top