سؤال

سواء System.Timers.Timer و System.Threading.Timer النار في فترات التي هي كبيرة مختلفة من المطلوب منها.على سبيل المثال:

new System.Timers.Timer(1000d / 20);

ينتج الموقت أن الحرائق 16 مرة في الثانية الواحدة ، وليس 20.

أن تكون على يقين من أن هناك أي آثار جانبية من فترة طويلة جدا معالجات الأحداث ، كتبت هذا الاختبار قليلا البرنامج:

int[] frequencies = { 5, 10, 15, 20, 30, 50, 75, 100, 200, 500 };

// Test System.Timers.Timer
foreach (int frequency in frequencies)
{
    int count = 0;

    // Initialize timer
    System.Timers.Timer timer = new System.Timers.Timer(1000d / frequency);
    timer.Elapsed += delegate { Interlocked.Increment(ref count); };

    // Count for 10 seconds
    DateTime start = DateTime.Now;
    timer.Enabled = true;
    while (DateTime.Now < start + TimeSpan.FromSeconds(10))
        Thread.Sleep(10);
    timer.Enabled = false;

    // Calculate actual frequency
    Console.WriteLine(
        "Requested frequency: {0}\nActual frequency: {1}\n",
        frequency, count / 10d);
}

الإخراج يبدو مثل هذا:

طلب:5 هرتز ؛ الفعلية:4,8 هرتز
طلب:10 هرتز ؛ الفعلية:9,1 هرتز
طلب:15 هرتز ؛ الفعلية:12,7 هرتز
طلب:20 هرتز ؛ الفعلية:16 هرتز
طلب:30 هرتز ؛ الفعلية:21,3 هرتز
طلب:50 هرتز ؛ الفعلية:31,8 هرتز
طلب:75 هرتز ؛ الفعلية:63,9 هرتز
طلب:100 هرتز ؛ الفعلية:63,8 هرتز
طلب:200 هرتز ؛ الفعلية:63,9 هرتز
طلب:500 هرتز ؛ الفعلية:63,9 هرتز

الفعلية تردد ينحرف بنسبة تصل إلى 36% من طلب واحد.(و من الواضح لا يمكن أن يتجاوز 64 هرتز.) بالنظر إلى أن توصي Microsoft هذا الموقت عن "دقة أكبر" على System.Windows.Forms.Timer, هذه الألغاز لي.

راجع للشغل, هذه ليست عشوائية الانحرافات.وهي نفس القيم في كل مرة.و اختبار مماثل برنامج توقيت آخر الصف ، System.Threading.Timer, يظهر نفس النتائج.

في بلدي الفعلية ، تحتاج إلى جمع القياسات بالضبط 50 عينة في الثانية.هذا ينبغي أن تتطلب نظام الوقت الحقيقي.وأنه أمر محبط للغاية للحصول على 32 عينة في الثانية بدلا من 50.

أي أفكار ؟

@كريس:أنت على حق, فترات كل يبدو أن مضاعفات عدد صحيح من شيء حول 1/64 ثانية.راجع للشغل, إضافة موضوع.النوم(...) في معالج الحدث لا يحدث أي فارق.هذا يبدو منطقيا بالنظر إلى أن System.Threading.Timer يستخدم تجمع مؤشرات الترابط ، لذلك كل حال أطلقت على الموضوع.

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

المحلول

أنا الحصول على عدد مختلف يصل إلى 100 هرتز في الواقع مع بعض الانحرافات ، ولكن في معظم الحالات أقرب إلى العدد المطلوب (تشغيل XP SP3 مع الأخيرة .صافي واص).

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

أود أن أقترح أن تنفيذ نوع من الموقت باستخدام مؤشر ترابط آخر (أو مزيج منها) يدعو النوم و رد.غير متأكد حول نتائج على الرغم من.

وإلا كنت قد نلقي نظرة على الوسائط المتعددة توقيت (PInvoke).

نصائح أخرى

إذا كنت تستخدم winmm.dll يمكنك استخدام المزيد من الوقت وحدة المعالجة المركزية، ولكن لديها سيطرة أفضل.

وهنا مثال المعدلة الخاصة بك لاستخدام توقيت winmm.dll

const String WINMM = "winmm.dll";
const String KERNEL32 = "kernel32.dll";

delegate void MMTimerProc (UInt32 timerid, UInt32 msg, IntPtr user, UInt32 dw1, UInt32 dw2);

[DllImport(WINMM)]
static extern uint timeSetEvent(
      UInt32            uDelay,      
      UInt32            uResolution, 
      [MarshalAs(UnmanagedType.FunctionPtr)] MMTimerProc lpTimeProc,  
      UInt32            dwUser,      
      Int32             fuEvent      
    );

[DllImport(WINMM)]
static extern uint timeKillEvent(uint uTimerID);

// Library used for more accurate timing
[DllImport(KERNEL32)]
static extern bool QueryPerformanceCounter(out long PerformanceCount);
[DllImport(KERNEL32)]
static extern bool QueryPerformanceFrequency(out long Frequency);

static long CPUFrequency;

static int count;

static void Main(string[] args)
{            
    QueryPerformanceFrequency(out CPUFrequency);

    int[] frequencies = { 5, 10, 15, 20, 30, 50, 75, 100, 200, 500 };

    foreach (int freq in frequencies)
    {
        count = 0;

        long start = GetTimestamp();

        // start timer
        uint timerId = timeSetEvent((uint)(1000 / freq), 0, new MMTimerProc(TimerFunction), 0, 1);

        // wait 10 seconds
        while (DeltaMilliseconds(start, GetTimestamp()) < 10000)
        {
            Thread.Sleep(1);
        }

        // end timer
        timeKillEvent(timerId);

        Console.WriteLine("Requested frequency: {0}\nActual frequency: {1}\n", freq, count / 10);
    }

    Console.ReadLine();
}

static void TimerFunction(UInt32 timerid, UInt32 msg, IntPtr user, UInt32 dw1, UInt32 dw2)
{
    Interlocked.Increment(ref count);
}

static public long DeltaMilliseconds(long earlyTimestamp, long lateTimestamp)
{
    return (((lateTimestamp - earlyTimestamp) * 1000) / CPUFrequency);
}

static public long GetTimestamp()
{
    long result;
    QueryPerformanceCounter(out result);
    return result;
}

وهنا هو إخراج أحصل على:

Requested frequency: 5
Actual frequency: 5

Requested frequency: 10
Actual frequency: 10

Requested frequency: 15
Actual frequency: 15

Requested frequency: 20
Actual frequency: 19

Requested frequency: 30
Actual frequency: 30

Requested frequency: 50
Actual frequency: 50

Requested frequency: 75
Actual frequency: 76

Requested frequency: 100
Actual frequency: 100

Requested frequency: 200
Actual frequency: 200

Requested frequency: 500
Actual frequency: 500

وآمل أن يساعد هذا.

وليس الغرض من هذه الطبقات للاستخدام في الوقت الحقيقي، وتخضع لطبيعة جدولة ديناميكية من نظام التشغيل مثل ويندوز. إذا كنت بحاجة إلى تنفيذ في الوقت الحقيقي ربما كنت ترغب في النظر في بعض الأجهزة المضمنة. أنا لست متأكدا 100٪ ولكن أعتقد .netcpu قد يكون نسخة في الوقت الحقيقي من وقت التشغيل .NET أصغر على شريحة.

http://www.arm.com/markets/emerging_applications/armpp /8070.html

وبطبيعة الحال - تحتاج إلى تقييم مدى دقة تعطى أهمية من تلك الفترات التي رمز تعلق عليها سوف يتم تنفيذ على نظام التشغيل الحقيقي غير. ما لم يكن بالطبع هذا هو السؤال الأكاديمية البحتة (في هذه الحالة - نعم أنها مثيرة للاهتمام: P).

ويبدو ان لديك الترددات الموقت الفعلية هي 63.9 هرتز أو عدد صحيح مضاعفاتها.

وهذا من شأنه أن ينطوي على قرار مؤقت من حوالي 15 مللي ثانية (أو مضاعفات عدد صحيح therefof، أي 30 ميللي ثانية، 45 ميللي ثانية، الخ.).

وهذا، توقيت على أساس مضاعفات صحيحة من 'القراد، أمر متوقع (في DOS على سبيل المثال "القراد" القيمة كانت 55 ميللي ثانية / 18 هرتز).

وأنا لا أعرف لماذا عدد التجزئة هو 15.65 MEC بدلا من حتى 15 ميللي ثانية. على سبيل التجربة، ما إذا كنت تنام لعدة ميللي ثانية داخل معالج الموقت: قد نكون رؤية 15 ميللي ثانية بين القراد، و0.65 ميللي ثانية في معالج جهاز ضبط الوقت الخاص بك في كل علامة

ويندوز (وبالتالي صافي تشغيل على أعلى من ذلك) هو نظام تشغيل متعدد المهام استباقي. أي موضوع معين يمكن أن تتوقف في أي وقت عن طريق موضوع آخر، وإذا لم تتصرف على موضوع استباق بشكل صحيح، فإنك لن تحصل على التحكم مرة أخرى عندما تريد ذلك أو <م> الحاجة ذلك.

وهذا، باختصار، هو السبب في أنك لا يمكن أن تكون مضمونة للحصول على توقيت بالضبط، ولماذا ويندوز و. NET على منصات مناسبة لأنواع معينة من البرامج. إذا حياتهم في خطر لأنك لا تحصل على التحكم بالضبط عندما تريد ذلك، واختيار منصة مختلفة.

إذا كنت بحاجة لجعل الانتقال إلى بيئة الوقت الحقيقي، ولقد استعملت RTX في الماضي عندما كانت هناك حاجة لأخذ العينات حتمية (من جهاز تسلسلي حسب الطلب)، وكان حظا سعيدا جدا معها.

http://www.pharlap.com/rtx.htm

وهنا هو تطبيق لطيفة من جهاز توقيت باستخدام الموقت الوسائط المتعددة HTTP: // شبكة الاتصالات العالمية. softwareinteractions.com/blog/2009/12/7/using-the-multimedia-timer-from-c.html

وهناك الكثير من الأسباب التي الترددات جهاز ضبط الوقت. المثال مع الأجهزة، وهو نفس موضوع مشغول مع معالجة أخرى، وهلم جرا ...

إذا كنت تريد المزيد من الوقت بدقة، استخدام فئة ساعة توقيت في مساحة System.Diagnostics.

جزء من المشكلة هو أن توقيت يكون اثنين التأخير إلى الحساب.وهذا يمكن أن تختلف اعتمادا على كيفية وتوقيت تنفيذها في نظام التشغيل.

  1. الوقت الذي طلب الانتظار
  2. الوقت بين عندما #1 يحدث عملية يحصل بدوره في جدولة قائمة الانتظار.

توقيت جيد سيطرة #1 ولكن تقريبا لا تتحكم #2.فإنه يمكن الإشارة إلى نظام التشغيل التي ترغب في تشغيل مرة أخرى ولكن نظام التشغيل هو حر في أن تستيقظ عندما يشعر مثل ذلك.

وبناء على تعليقاتكم، ويجب أن لا يكون باستخدام جهاز توقيت على الإطلاق. يجب أن تكون باستخدام حلقة مع ساعة توقيت للتحقق من فترة وspinlock حتى انك لا تفقد الكم.

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