10

タイムスタンプを使用して、何かが画面に表示されている時間の統計を計算する Cocoa OS X (Leopard 10.5+) エンドユーザー プログラムを作成しています。プログラムが繰り返し NSTimer を使用して実行されている間、時間は定期的に計算されます。 タイムスタンプ、 StartおよびFinish[NSDate date]をキャプチャするために使用されます。2 つの日付の差を秒単位で計算するのは簡単です。

エンド ユーザーまたは ntp がシステム クロックを変更すると、問題が発生します。 [NSDate date]システムクロックに依存しているため、変更された場合、Finish変数はStartに対して相対的にずれ、時間の計算が大幅に混乱します。私の質問:

1.システムクロックが途中で変更された場合でも、StartFinishの間の時間を秒単位で正確に計算するにはどうすればよいですか?

それから何秒経過したかを計算できるように、変更されていない基準時点が必要だと考えています。たとえば、システムの稼働時間です。10.6 には があり- (NSTimeInterval)systemUptime、 の一部でありNSProcessInfo、システムのアップタイムを提供します。ただし、私のアプリは 10.5 で動作する必要があるため、これは機能しません。

NSTimer を使用してタイム カウンターを作成しようとしましたが、これは正確ではありません。NSTimer にはいくつかの異なる実行モードがあり、一度に 1 つしか実行できません。NSTimer (デフォルト) はデフォルトの実行モードになります。ユーザーが長時間 UI の操作を開始すると、NSEventTrackingRunLoopModeに入り、デフォルトの実行モードをスキップします。これにより、NSTimer の起動がスキップされ、秒数を正確にカウントできなくなります。

また、別のスレッド (NSRunLoop) を作成して NSTimer 秒カウンターを実行し、UI インタラクションから遠ざけることも考えました。しかし、私はマルチスレッドに非常に慣れていないので、可能であればそれを避けたいと思っています。また、CPU が別のアプリケーション (大きな画像をレンダリングする Photoshop など) によってペグされた場合にこれが正確に機能するかどうかはわかりません。 NSタイマー。

助けていただければ幸いです。:)

4

3 に答える 3

5

このコードを駆動しているものに応じて、2つの選択肢があります。

  • 絶対精度を得るには、を使用しますmach_absolute_time()。関数を呼び出したポイント間の時間間隔が正確に示されます。
  • しかし、GUIアプリでは、これは実際には望ましくないことがよくあります。代わりに、期間を開始したイベントと終了したイベントの時間差が必要です。もしそうなら、比較[[NSApp currentEvent] timestamp]
于 2009-10-27T00:26:17.470 に答える
2

さて、これはロングショットですが、SnowLeopardでNSSystemClockDidChangeNotification利用可能なようなものを実装してみることができます。

これは奇妙な考えであり、間違いなく非決定論的であるため、ここで私に耐えてください。しかし、プログラムの実行中にウォッチドッグスレッドが実行されていた場合はどうなるでしょうか。このスレッドは、n秒ごとに、システム時刻を読み取って保存します。議論のために、5秒にしておきましょう。したがって、5秒ごとに、前回の読み取り値を現在のシステム時刻と比較します。「十分に大きい」違いがある場合(「十分に大きい」は間違いなく5より大きい必要がありますが、大きすぎないようにする必要があります)さらに、プロセスのスケジューリングとスレッドの優先順位付けの非決定性を説明するために、大幅な時間変更があったという通知を投稿してください。精度のニーズに応じて、「十分に大きい」(または、クロックが以前の時間にリセットされた場合は十分に小さい)を構成する値をファジングする必要があります。

これは一種のハッキーだと思いますが、他の解決策を除けば、どう思いますか?それ、またはそのようなものがあなたの問題を解決するでしょうか?

編集

さて、あなたは元の質問を修正して、マルチスレッドに慣れていないのでウォッチドッグスレッドを使用したくないと言った。あなたが慣れているよりも少し進んだことをすることへの恐れは理解していますが、これが唯一の解決策になるかもしれません。その場合、あなたはやるべきことを少し読む必要があるかもしれません。=)

そして、ええ、私は、Photoshopがプロセッサからがらくたを釘付けにするような何かが問題であることを知っています。別の(さらに複雑な)解決策は、ウォッチドッグスレッドを使用する代わりに、最優先の個別のウォッチドッグプロセスを使用して、プロセッサのペギングの影響を受けないようにすることです。しかし、繰り返しになりますが、これは非常に複雑になっています。

最終編集

完全を期すために、上記の他のすべてのアイデアを残しておきますが、システムの稼働時間を使用することも、これに対処するための有効な方法になると思われます。10.6以降[[NSProcessInfo processInfo] systemUptime]でのみ機能するため、を呼び出すだけmach_absolute_time()です。その関数にアクセスするには、#include <mach/mach_time.h>。これは、によって返される値と同じである必要がありますNSProcessInfo

于 2009-10-26T22:52:26.320 に答える
1

で提供されているUpTime() C 関数を使用してこれを行う方法を見つけました<CoreServices/CoreServices.h>。これは、持続時間 (ミリ秒またはナノ秒) に簡単に変換できる絶対時間 (CPU 固有) を返します。詳細はこちら: http://www.meandmark.com/timingpart1.html (UpTime についてはパート 3 を参照)

mach_absolute_time()おそらくそれに関する知識がなく、ウェブ上でそれに関する多くのドキュメントを見つけることができなかったため、適切に作業することができませんでした。と同じ時間をつかんでいるように見えますがUpTime()、ダブルに変換すると唖然としました。

[[NSApp currentEvent] timestamp]動作しましたが、アプリケーションが NSEvents を受信して​​いた場合のみです。アプリケーションがフォアグラウンドになった場合、アプリケーションはイベントを受信せず[[NSApp currentEvent] timestamp]、エンドユーザーが再びアプリと対話することを決定するまで、NSTimer 起動メソッドで同じ古いタイムスタンプを何度も返し続けます。

マークとマイク、ご協力ありがとうございました!あなたは間違いなく私を正しい方向に送り、答えに導きました. :)

于 2009-10-27T19:17:27.533 に答える