حساب عدد الثواني بين نقطتين في الوقت المناسب ، في الكاكاو ، حتى عندما تتغير ساعة النظام في منتصف الطريق

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

سؤال

أنا أكتب برنامجًا للمستخدم النهائي Cocoa OS X (Leopard 10.5+) يستخدم الطابع الزمني لحساب الإحصائيات حول المدة التي يتم عرض شيء ما على الشاشة. يتم حساب الوقت بشكل دوري أثناء تشغيل البرنامج باستخدام Nstimer المتكرر. [NSDate date] يستخدم لالتقاط الطوابع الزمنية ، بداية و إنهاء. حساب الفرق بين التواريخ في الثواني هو تافهة.

تحدث مشكلة إذا قام المستخدم النهائي أو NTP بتغيير ساعة النظام. [NSDate date] يعتمد على ساعة النظام ، لذلك إذا تم تغييره ، إنهاء سيتم منحرف المتغير بالنسبة إلى بداية, ، العبث بحساب الوقت بشكل كبير. سؤالي:

1. كيف يمكنني حساب الوقت بين بداية و إنهاء, ، في ثوان ، حتى عندما يتم تغيير ساعة النظام في منتصف الطريق؟

أفكر في أنني بحاجة إلى نقطة مرجعية غير متغيرة في الوقت المناسب حتى أتمكن من حساب عدد الثواني التي مرت منذ ذلك الحين. على سبيل المثال ، وقت تشغيل النظام. 10.6 لديه - (NSTimeInterval)systemUptime, ، جزء من NSProcessInfo, ، والذي يوفر وقت تشغيل النظام. ومع ذلك ، لن يعمل هذا لأن تطبيقي يجب أن يعمل في 10.5.

لقد حاولت إنشاء عداد زمني باستخدام Nstimer ، لكن هذا ليس دقيقًا. يحتوي Nstimer على العديد من أوضاع التشغيل المختلفة ويمكنه تشغيل واحدة فقط في وقت واحد. يتم وضع nstimer (بشكل افتراضي) في إفتراضي وضع التشغيل. إذا بدأ المستخدم في معالجة واجهة المستخدم لفترة طويلة بما فيه الكفاية ، فسيؤدي ذلك إلى الدخول nseventtrackingrunloopmode وتخطي فوق إفتراضي وضع التشغيل ، والذي يمكن أن يؤدي إلى تخطي إطلاق نارستايمر ، مما يجعله وسيلة غير دقيقة لحساب الثواني.

لقد فكرت أيضًا في إنشاء موضوع منفصل (nsrunloop) لتشغيل قناة ثانية nstimer ، مع إبقائه بعيدًا عن تفاعلات واجهة المستخدم. لكنني جديد جدًا على متعدد الخيوط وأود الابتعاد عن ذلك إن أمكن. أيضًا ، لست متأكدًا مما إذا كان هذا سيعمل بدقة في حالة ربط وحدة المعالجة المركزية بتطبيق آخر (Photoshop يضع صورة كبيرة ، إلخ ...) ، مما يؤدي إلى تعليق NSrunloop الخاص بي لفترة طويلة بما يكفي لإفسادها nstimer.

أنا أقدر أي مساعدة. قون

هل كانت مفيدة؟

المحلول 3

اكتشفت طريقة للقيام بذلك باستخدام مدة التشغيل() C وظيفة ، متوفرة في <CoreServices/CoreServices.h>. هذا يعود الوقت المطلق (خاص بوحدة المعالجة المركزية) ، والتي يمكن تحويلها بسهولة إلى وقت المدة (ميلي ثانية ، أو نانو ثانية). التفاصيل هنا: http://www.meandmark.com/timingpart1.html (انظر تحت الجزء 3 لوقت التشغيل)

لم أستطع الحصول عليها mach_absolute_time() للعمل بشكل صحيح ، على الأرجح بسبب افتقاري إلى المعرفة عليه ، وعدم القدرة على العثور على الكثير من الوثائق على الويب حول هذا الموضوع. يبدو أن الاستيلاء في نفس الوقت كما UpTime(), ، ولكن تحويله إلى مزدوج ترك لي مصعوبة.

[[NSApp currentEvent] timestamp] هل نجحت ، ولكن فقط إذا كان التطبيق يتلقى الأبحاث. إذا دخل التطبيق في المقدمة ، فلن يتلقى الأحداث ، و [[NSApp currentEvent] timestamp] سيستمر ببساطة في إعادة الطابع الزمني القديم مرة أخرى مرارًا وتكرارًا في طريقة إطلاق النار ، حتى قرر المستخدم النهائي التفاعل مع التطبيق مرة أخرى.

شكرا على كل مساعدتك مارك ومايك! لقد أرسلت لي بالتأكيد في الاتجاه الصحيح مما يؤدي إلى الإجابة. قون

نصائح أخرى

اعتمادًا على ما يقود هذا الرمز ، لديك خياران:

  • للدقة المطلقة ، استخدم mach_absolute_time(). سوف يعطي الفاصل الزمني بالضبط بين النقاط التي اتصلت بها الوظيفة.
  • ولكن في تطبيق واجهة المستخدم الرسومية ، غالبًا ما يكون هذا غير مرغوب فيه. بدلاً من ذلك ، تريد الفرق بين الوقت بين الأحداث بدأ ذلك وانتهى من مدتك. إذا كان الأمر كذلك ، قارن [[NSApp currentEvent] timestamp]

حسنًا ، هذه لقطة طويلة ، ولكن يمكنك محاولة تنفيذ شيء ما مثل NSSystemClockDidChangeNotification متوفر في الثلج ليوبارد.

لذا احمل معي هنا ، لأن هذه فكرة غريبة وهي بالتأكيد غير مهوودية. ولكن ماذا لو كان لديك خيط مراقبة يعمل خلال مدة البرنامج؟ هذا الموضوع ، كل ثواني n ، يقرأ وقت النظام وتخزينه. من أجل الحجة ، دعنا فقط نجعلها 5 ثوان. لذلك كل 5 ثوان ، يقارن القراءة السابقة بوقت النظام الحالي. إذا كان هناك اختلاف "كبير بما يكفي" ("سيحتاج" كبير بما فيه الكفاية "إلى أن يكون بالتأكيد أكبر من 5 ، ولكن ليس كثير جدا أكبر ، لحساب عدم تحديد جدولة العملية وتحديد أولويات الخيط) ، نشر إشعارًا بأنه كان هناك تغيير كبير في الوقت. ستحتاج إلى اللعب مع ضجة القيمة التي تشكل "كبيرة بما يكفي" (أو صغيرة بما يكفي ، إذا تم إعادة تعيين الساعة إلى وقت سابق) لتلبية احتياجات دقتك.

أعلم أن هذا نوع من الاختراق ، ولكن باستثناء أي حل آخر ، ما رأيك؟ قد يحل ذلك ، أو شيء من هذا القبيل ، مشكلتك؟

يحرر

حسنًا ، قمت بتعديل سؤالك الأصلي لتقول أنك لا تفضل استخدام موضوع ترابط لأنك جديد في MultiThreading. أفهم الخوف من فعل شيء أكثر تقدماً مما تشعر به ، لكن هذا قد ينتهي به الأمر هو الحل الوحيد. في هذه الحالة ، قد يكون لديك القليل من القراءة للقيام به. =)

ونعم ، أنا أعلم أن شيئًا مثل Photoshop يربط حماقة من المعالج يمثل مشكلة. هناك حل آخر (أكثر تعقيدًا) هو ، بدلاً من وجود مراقبة مسلك, ، لديك مراقبة منفصلة معالجة هذا له أولوية قصوى ، لذا فهو أكثر محصنة من ربط المعالج. ولكن مرة أخرى ، هذا هو التعقيد حقا.

التحرير النهائي

سأترك جميع أفكاري الأخرى أعلاه من أجل الاكتمال ، ولكن يبدو أن استخدام وقت تشغيل النظام سيكون أيضًا وسيلة صالحة للتعامل مع هذا. حيث [[NSProcessInfo processInfo] systemUptime] يعمل فقط في 10.6+ ، يمكنك الاتصال فقط mach_absolute_time(). للوصول إلى هذه الوظيفة ، فقط #include <mach/mach_time.h>. يجب أن تكون نفس القيمة التي تم إرجاعها بواسطة NSProcessInfo.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top