2010-11-18 53 views
15

में ईवेंट बढ़ाएं मैं C# का उपयोग कर उच्चतम संभावित रिज़ॉल्यूशन टाइमर का उपयोग करना चाहता हूं। उदाहरण के लिए, मैं प्रत्येक 11 टिकों को एक ईवेंट बनाना चाहता हूं (आईव ने सुना है कि टिक पीसी में सबसे ज्यादा संभव काउंटर है)। मैंने टाइमर की कोशिश की और पाया कि न्यूनतम विलंब समय मिलीसेकंड में है। स्टॉपवॉच पर देखा लेकिन स्टॉपवॉच घटनाओं को नहीं बढ़ाता है।उच्च रिज़ॉल्यूशन अंतराल/टाइमर

धन्यवाद।

+2

क्यों दुनिया में आप हर 11 टिकों को एक ईवेंट उठाना चाहते हैं? क्या आप इसे कोड प्रोफाइलिंग के लिए उपयोग कर रहे हैं? –

+5

आप सवालों का जवाब नहीं दे रहे हैं। 11 टिक सिर्फ उदाहरण है। मैं चाहता हूं कि उच्च रिज़ॉल्यूशन टाइमर हो। यदि संभव हो, तो 1 टिक तक। और हाँ, मैं कुछ बेंचमार्क करने के लिए एक आवेदन विकसित कर रहा हूँ। –

+0

यही कारण है कि मैं डाउनवॉटिंग टिप्पणियों का समर्थन करता हूं –

उत्तर

18

मल्टीमीडिया टाइमर का उपयोग करके आपको प्रति सेकंड 1000 घटनाएं मिलनी चाहिए। इस कोड को आपको रास्ते में मदद करनी चाहिए।

 public delegate void TimerEventHandler(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2); 

    /// <summary> 
    /// A multi media timer with millisecond precision 
    /// </summary> 
    /// <param name="msDelay">One event every msDelay milliseconds</param> 
    /// <param name="msResolution">Timer precision indication (lower value is more precise but resource unfriendly)</param> 
    /// <param name="handler">delegate to start</param> 
    /// <param name="userCtx">callBack data </param> 
    /// <param name="eventType">one event or multiple events</param> 
    /// <remarks>Dont forget to call timeKillEvent!</remarks> 
    /// <returns>0 on failure or any other value as a timer id to use for timeKillEvent</returns> 
    [DllImport("winmm.dll", SetLastError = true,EntryPoint="timeSetEvent")] 
    static extern UInt32 timeSetEvent(UInt32 msDelay, UInt32 msResolution, TimerEventHandler handler, ref UInt32 userCtx, UInt32 eventType); 

    /// <summary> 
    /// The multi media timer stop function 
    /// </summary> 
    /// <param name="uTimerID">timer id from timeSetEvent</param> 
    /// <remarks>This function stops the timer</remarks> 
    [DllImport("winmm.dll", SetLastError = true)] 
    static extern void timeKillEvent( UInt32 uTimerID); 

इन्हें चलाने के बाद इन टाइमर को रोकें। वे आपके सिस्टम पर काफी भारी हैं *। सभी अपवादों को पकड़ें और उन्हें अपने ईवेंट हैंडलर से बचने न दें।

* अधिक से अधिक 5 टाइमर अधिकतर सिस्टम को गंभीरता से धीमा कर देंगे! ईवेंट हैंडलर में जितना संभव हो सके कोड निष्पादित करें और सुनिश्चित करें कि निष्पादन कोड तेज़ है तो 1 मिलीसेकंड या गंभीर समस्याएं हैं। मैंने एक लेबल डिस्प्ले बढ़ाने के लिए हर 10-50 टिकों में एक प्रतिनिधि को शुरू किया।

Thread.Sleep पर होने वाला एक सामान्य थ्रेड स्विच आपके थ्रेड-स्लॉट को आपके कोड से मुक्त कर देगा और लगभग 40 मिलीसेकंड लेगा। आप कुछ एनटी कर्नेल कॉल के साथ थ्रेड स्विच फ्रीक्वेंसी भी बढ़ा सकते हैं, लेकिन कृपया ऐसा न करें।

4

विभिन्न टाइमर कक्षाएं एक बड़ी ग्रैन्युलरिटी का उपयोग करती हैं। थ्रेडिंग दोनों। टिमर और टाइमर। टाइमर 1/64 सेकेंड का उपयोग करें, जो 15.625 मिलीसेकंड है।

यदि आप 'टिक' का जिक्र कर रहे हैं तो 100 नैनोसेकंद टिक है, जो डेटटाइम क्लास, टाइमस्पेन क्लास और स्टॉपवॉच द्वारा आउटपुट द्वारा उपयोग की जाती है, तो 11 टिक लंबाई जो आप पूछ रहे हैं वह 1,100 नैनोसेकंड है, या 1.1 माइक्रोसॉन्ड। मेरे सबसे अच्छे ज्ञान के लिए, कोई अंतर्निहित टाइमर नहीं है जो आपको वह रिज़ॉल्यूशन देगा। यदि आप वास्तव में प्रत्येक 1.1 माइक्रोसॉन्ड होने की घटना चाहते हैं, तो आपको 'टाइमर' के विचार को हटाना होगा, और इसके बजाय थोड़ी देर के मामले में सोचना होगा। थ्रेड उच्च प्राथमिकता बनाएं, और अपनी घटना को लूप में चलाएं। थ्रेड को कॉल न करें। नींद(), क्योंकि मेरा मानना ​​है कि 1.1 माइक्रोसॉंड सिस्टम शेड्यूलर के टाइमलाइस से छोटा है। आपको इसके बजाय देरी लूप करना होगा।

इसके अलावा, यह महसूस करें कि आप जिस समय अंतराल के बारे में पूछ रहे हैं वह बहुत छोटा है। 1.1 माइक्रोसॉन्ड 2 गीगाहर्ट्ज प्रोसेसर पर केवल 2,200 प्रोसेसर चक्र हैं। एक महत्वहीन राशि नहीं है, लेकिन अधिक काम करने के लिए बहुत समय नहीं है। यदि आप अपनी टिप्पणी में 1 टिक की बात कर रहे हैं, तो यह केवल 200 प्रोसेसर चक्र है: यह कुछ दर्जन गणित संचालन करने के लिए पर्याप्त समय है, और शायद एक समारोह को कॉल कर सकता है।

+0

मुझे जो दिलचस्पी है वह स्टॉपवॉच है। फ्रीक्वेंसी थोडा टिक। दूसरे शब्दों में, प्रोसेसर चक्र टिक। –

+3

प्रोसेसर चक्र टिक, उदाहरण के लिए, 2 गीगाहर्ट्ज? वह 0.5 नैनोसेकंड है। सबसे सरल प्रोसेसर निर्देशों को छोड़कर सभी प्रोसेसर चक्र लेते हैं। उदाहरण के लिए, आप एक चक्र में एक पूर्णांक बढ़ाने में सक्षम हो सकते हैं, लेकिन एक 'if' कथन? कोई रास्ता नहीं, यह 10 प्रोसेसर चक्र, 5 नैनोसेकंड के आदेश पर है। उस आवृत्ति पर टाइमर की जांच करने का कोई तरीका नहीं है, बहुत कम काम किया जाता है। –

+4

रुको, मैं इसे वापस लेता हूं। 1 प्रोसेसर चक्र की आवृत्ति के साथ टाइमर रखने का एक तरीका है: थ्रेड को उच्च प्राथमिकता पर सेट करें और 'जबकि (सत्य) {...} ' –

14

सबसे पहले, आपको यह समझने की आवश्यकता है कि हार्डवेयर और सॉफ़्टवेयर दोनों द्वारा उजागर सीमाओं के कारण कंप्यूटर पर सटीक समय करने के लिए असंभव नहीं है, तो यह बेहद मुश्किल है। अच्छी खबर यह है कि इस तरह की परिशुद्धता शायद ही कभी जरूरी है। दस टिक एक बहुत कम समय की मात्रा है। इस अंतराल में सीपीयू द्वारा बहुत कम काम किया जा रहा है, और यह सांख्यिकीय रूप से महत्वपूर्ण नहीं होगा।

संदर्भ के लिए, विंडोज घड़ी में लगभग 10 मिलीसेकंड (पिछले संस्करणों पर कम) की सटीकता है। DateTime.UtcNow पर कॉल के साथ अपना कोड लपेटना उससे बेहतर नहीं होगा।

अपने प्रश्न में, आप "एक घटना उठाएं" चाहते हैं। समस्या यह है कि एकमात्र प्रकार की समय-सारणी वस्तु जो विशिष्ट अंतराल पर एक ईवेंट उठाती है Timer ऑब्जेक्ट है। यह .NET Framework (System.Timers.Timer, System.Threading.Timer, और System.Windows.Forms.Timer) में 3 अलग-अलग अवतारों में उपलब्ध है, जिनमें से सभी का अपना अनूठा उपयोग परिदृश्य और सापेक्ष quirks है, लेकिन उनमें से कोई भी के लिए जो भी पूछ रहा है उसके करीब कहीं भी परिशुद्धता की गारंटी देता है । उन्हें ऐसा करने के लिए भी डिज़ाइन नहीं किया गया है, और न ही ऐसे विंडोज़ एपीआई द्वारा खुलासा किया गया कोई समकक्ष कार्य है जो इस प्रकार की सटीकता प्रदान करने जा रहे हैं।

कारण मैंने पूछा कि आप ऐसा क्यों करना चाहते हैं और यदि आप बेंचमार्क का प्रयास कर रहे हैं तो यह पूरे गेम को बदल देता है। .NET Framework (संस्करण 2.0 के रूप में) Stopwatch object प्रदान करता है जिसे स्पष्ट रूप से बेंचमार्किंग या प्रदर्शन प्रोफाइलिंग जैसी स्थिति के लिए सटीक रूप से मापने के लिए डिज़ाइन किया गया है। Stopwatch बस विंडोज एपीआई फ़ंक्शंस QueryPerformanceFrequency और QueryPerformanceCounter (जो इसके सुझाव के अनुसार मेरे सुझाव की पुष्टि करनी चाहिए) को लपेटता है। फ्रेमवर्क के पुराने संस्करणों में इस प्रकार की कार्यक्षमता तक पहुंचने के लिए हमें इन कार्यों को पी/इनवॉक करना होता था, लेकिन अब यह आसानी से बनाया गया है। यदि आपको बेंचमार्किंग के लिए अपेक्षाकृत उच्च रिज़ॉल्यूशन वाले टाइमर की आवश्यकता है, तो Stopwatch आपकी सर्वश्रेष्ठ शर्त है । सिद्धांत रूप में, यह आपको उप-माइक्रोसॉन्ड समय प्रदान कर सकता है।

लेकिन यह इसकी समस्याओं के बिना नहीं है। यह किसी भी घटना को नहीं बढ़ाता है, इसलिए यदि आपका वर्तमान डिज़ाइन इवेंट हैंडलिंग पर निर्भर करता है, तो आपको इसे पुनर्विचार करना होगा। और, यह पूरी तरह सटीक होने की गारंटी नहीं है, या तो। निश्चित रूप से, उच्चतम संभावित रिज़ॉल्यूशन हार्डवेयर बाधाओं के कारण हो सकता है, लेकिन इसका मतलब यह नहीं है कि यह आवश्यक रूप से आपकी निर्दिष्ट आवश्यकताओं को पूरा करेगा। उदाहरण के लिए, यह एकाधिक प्रोसेसर सिस्टम पर अविश्वसनीय हो सकता है जहां Start और Stop को उसी प्रोसेसर पर निष्पादित किया जाना है। इससे कोई फर्क नहीं पड़ता, लेकिन it does। प्रोसेसर पर यह subject to being unreliable भी है जो अपनी घड़ी की गति को ऊपर और नीचे थ्रॉटल कर सकता है। और हिम्मत भी है कि मैं यह भी उल्लेख करता हूं कि QueryPerformanceCounter पर कॉल करने के लिए कुछ समय-समय पर लगभग 5 माइक्रोसॉन्ड भी आधुनिक 2+ गीगाहर्ट्ज प्रोसेसर पर जा रहा है, जो आपको वास्तव में उस उप-माइक्रोसॉन्ड समय को प्राप्त करने में सक्षम होने से रोकता है जो सिद्धांत में अच्छा लगता है। फिर फिर, कोई भी उचित कोड प्रोफाइलर उस समय पर नगण्य समय पर विचार करेगा क्योंकि, यह है।
(यह भी देखें: http://www.devsource.com/c/a/Techniques/High-Performance-Timing-under-Windows/2/)

+0

लांघी व्याख्या के लिए धन्यवाद। यदि, उदाहरण के लिए, मैं वास्तविक समय ओएस का उपयोग करता हूं, क्या मुझे उस तरह का उच्च परिशुद्धता टाइमर मिल सकता है? विंडोज सर्वर एक वास्तविक समय ओएस है? धन्यवाद। –

+2

यदि आप आरटीओएस का उपयोग करते हैं, तो आपको उच्च रिज़ॉल्यूशन टाइमर का मौका मिल सकता है। हालांकि, वास्तविक समय ओएस का मतलब यह नहीं है कि चीजें तुरंत होती हैं, लेकिन वे एक ज्ञात समय सीमा के भीतर होती हैं, इसलिए आप अभी भी उतना सटीक समय नहीं ले सकते जितना आप सोच रहे हैं। विंडोज के लिए आरटीओएस होने के नाते, निश्चित रूप से नहीं। –

+1

@publicENEMY: डेविड यॉ की प्रतिक्रिया सही है। यहां तक ​​कि विंडोज़ के सर्वर संस्करण रीयल-टाइम ऑपरेटिंग सिस्टम नहीं हैं (मैं वर्कस्टेशन के रूप में विंडोज सर्वर चलाता हूं, यह इतना अलग नहीं है)। यह भी ध्यान देने योग्य है कि ओएस द्वारा उजागर की गई सॉफ्टवेयर सीमाओं को पार करने के बावजूद, आपको अभी भी सामान्य पीसी हार्डवेयर की सीमाओं का सामना करना पड़ेगा। यदि आप ओएस को स्विच करने पर विचार कर रहे हैं, तो * जो भी आप प्राप्त करने की कोशिश कर रहे हैं उसे करने के लिए एक बेहतर तरीका होना चाहिए। –

संबंधित मुद्दे

 संबंधित मुद्दे