2010-06-08 20 views
9

दोनों थ्रेड। स्लीप (टाइमआउट) और resetEvent.Wait (टाइमआउट) कम से कम timeout मिलीसेकंड के लिए निष्पादन का कारण बनता है, तो क्या उनके बीच कोई अंतर है? मुझे पता है कि थ्रेड। नींद थ्रेड को अपने शेष समय के टुकड़े को छोड़ने का कारण बनती है, इस प्रकार संभवतः एक नींद होती है जो पूछने से कहीं अधिक लंबी होती है। क्या ManualResetEvent ऑब्जेक्ट की प्रतीक्षा (टाइमआउट) विधि एक ही समस्या है?Thread.Sleep (टाइमआउट) और ManualResetEvent.Wait (टाइमआउट) के बीच क्या अंतर है?

संपादित: मुझे पता है कि एक ManualResetEvent के मुख्य बिंदु एक और धागे से संकेत किया जा रहा है हूँ - अभी मैं केवल निर्दिष्ट समय समाप्त के साथ एक घटना के इंतजार विधि के मामले के साथ सवाल है, और कोई अन्य कॉल की स्थापना घटना। मैं जानना चाहता हूँ कि क्या यह समय पर Thread.Sleep

से जगाने के लिए अधिक विश्वसनीय है चाहता हूँ

उत्तर

21

Thread.Sleep(timeout) निष्पादन शुरू होने से पहले बिना शर्त प्रतीक्षा का कारण बनता है। resetEvent.WaitOne(timeout) थ्रेड का इंतजार तब तक करता है जब तक कि ईवेंट (1) ईवेंट ट्रिगर नहीं होता है, या (2) टाइमआउट पहुंच जाता है।

घटनाओं का उपयोग करने का बिंदु उन्हें किसी अन्य धागे से ट्रिगर करना है, ताकि थ्रेड उठने पर आप सीधे नियंत्रण कर सकें। यदि आपको इसकी आवश्यकता नहीं है, तो आपको ईवेंट ऑब्जेक्ट्स का उपयोग नहीं करना चाहिए।

संपादित करें: समय-समय पर, वे दोनों समान रूप से विश्वसनीय हैं। हालांकि, "समय पर जागृति" के बारे में आपकी टिप्पणी मुझे चिंतित करती है। समय पर जागने के लिए आपको अपने कोड की आवश्यकता क्यों है? Sleep और WaitOne वास्तव में दिमाग में सटीकता के साथ डिजाइन नहीं किए गए हैं।

केवल timeout 50ms से कम या तो है और आपको विश्वसनीयता की आवश्यकता है, तो आपको समय के वैकल्पिक तरीकों को देखना चाहिए। This article एक बहुत अच्छा अवलोकन की तरह दिखता है।

+0

मुझे पता है कि; मैं वास्तव में टाइमआउट मामले में केवल रूचि रखता हूं। मैं जानना चाहता हूं कि थ्रेड से समय पर जागने के लिए यह अधिक विश्वसनीय है या नहीं। नींद –

+0

थ्रेड करता है। स्लीप ब्लॉक COM संदेश और घटनाएं? अगर हमें कुछ सेकंड के लिए मुख्य धागे में देरी की आवश्यकता है, जिसका उपयोग थ्रेड किया जाना चाहिए। सो जाओ या प्रतीक्षा करें ??? – lerner1225

8

Thread.Sleep और ManualResetEvent.WaitOne के बीच मुख्य अंतर यह है कि आप एक धागा एक ManualResetEvent Set विधि का उपयोग पर इंतजार करने के लिए संकेत दे सकता है जगाने के लिए धागा पैदा कर रहा है टाइमआउट से पहले ऊपर।

यदि आप संकेत नहीं देते हैं तो मैं उम्मीद करता हूं कि वे एक समान तरीके से व्यवहार करें।

नेट परावर्तक से मैं देख सकता हूँ कि विधि ManualResetEvent.WaitOne अंत में निम्नलिखित हस्ताक्षर के साथ एक निर्वासन विधि के लिए एक कॉल में परिणाम:

void SleepInternal(int millisecondsTimeout); 

:

int WaitOneNative(SafeWaitHandle waitHandle, 
        uint millisecondsTimeout, 
        bool hasThreadAffinity, 
        bool exitContext); 

Thread.Sleep जबकि इस निर्वासन विधि कॉल दुर्भाग्यवश मेरे पास इन विधियों के लिए स्रोत कोड नहीं है, इसलिए मैं केवल अनुमान लगा सकता हूं। मैं कल्पना करता हूं कि दोनों कॉलों में थ्रेड का समय समाप्त हो जाएगा, जबकि यह समाप्त होने का समय इंतजार कर रहा है, न कि दूसरे से विशेष रूप से अधिक सटीक होना।

1

नींद निर्दिष्ट समय के लिए जारी है। इवेंट सिग्नल होने पर इवेंट प्रतीक्षा जल्द खत्म हो सकता है। यह घटनाओं का उद्देश्य है: एक थ्रेड को जागने के लिए किसी अन्य को बताने की अनुमति देना।

एक थ्रेड में आप कहेंगे:

mre.WaitOne(10000); // ten seconds 
    Console.WriteLine("Woke up!"); 

एक और में आप कहेंगे:

mre.Set(); // this causes `WaitOne` to return in the first thread 
अन्य सूत्र में Set करने के लिए कॉल के बिना

, पहले धागा प्रभावी ढंग से सो होगा दस पल।

1

जैसा कि अन्य ने उल्लेख किया है, अंतर है प्रतीक्षा करें अगर संकेत दिया जाता है तो नींद के समय से पहले वापस आ सकता है। सोने की नींद के समय की प्रतीक्षा करने की गारंटी है।

परावर्तक कॉल में Thread.Sleep:

[MethodImpl(MethodImplOptions.InternalCall)] 
private static extern void SleepInternal(int millisecondsTimeout); 

परावर्तक कॉल में ManualResetEvent.Wait:

private static extern int WaitOneNative(SafeWaitHandle waitHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext); 

सुनिश्चित नहीं हैं कि अगर इन दोनों के बीच एक अंतर है, लेकिन मैं अगर देखेंगे कि मैं कुछ मिल सकता है

4

नींद() फ़ंक्शन लंबे समय तक इस तरह से काम नहीं करता है। इसकी सटीकता मल्टीमीडिया टाइमर अवधि द्वारा निर्धारित की जाती है, जिसे आप पी/Invoking timeBeginPeriod() द्वारा बदल सकते हैं। दुर्भाग्यवश, मेरी मशीन पर मुझे कुछ प्रकार का प्रोग्राम मिला है जो इस अवधि को एक मिलीसेकंड में सेट करता है, जिससे मिलीसेकंड तक सटीक नींद आती है। के बारे में 5 मिलीसेकेंड की परिवर्तनशीलता के साथ 1003

: यहाँ अपने आप के लिए प्रयास करने के लिए कुछ कोड है: मेरी मशीन पर

using System; 
using System.Diagnostics; 
using System.Threading; 
using System.Runtime.InteropServices; 

class Program { 
    static void Main(string[] args) { 
     //timeBeginPeriod(1); 
     var sw1 = Stopwatch.StartNew(); 
     for (int ix = 0; ix < 100; ++ix) Thread.Sleep(10); 
     sw1.Stop(); 
     var sw2 = Stopwatch.StartNew(); 
     var mre = new ManualResetEvent(false); 
     for (int ix = 0; ix < 100; ++ix) mre.WaitOne(10); 
     sw1.Stop(); 
     Console.WriteLine("Sleep: {0}, Wait: {1}", sw1.ElapsedMilliseconds, sw2.ElapsedMilliseconds); 
     Console.ReadLine(); 
     //timeEndPeriod(1); 
    } 
    [DllImport("winmm.dll")] 
    private static extern int timeBeginPeriod(int period); 
    [DllImport("winmm.dll")] 
    private static extern int timeEndPeriod(int period); 
} 

आउटपुट:

नींद: 999, प्रतीक्षा करें।

+0

आप के लिए कोई संदर्भ नहीं है, क्या आप? –

+0

एमएसडीएन पुस्तकालय में स्लीप() के लिए एसडीके दस्तावेज़ देखें। –

5

देरी और periodics के लिए मैं पाया है एक अच्छा विकल्प Monitor.Wait ..

object timelock = new object(); 

lock (timelock) { Monitor.Wait(timelock, TimeSpan.FromMilliseconds(X.XX)); } 

यह आवेदन बारीकियों के आधार पर बेहतर एक उत्कृष्ट परिणाम .... ~ 1ms घबराना देता है या।

जैसा कि आप पहले से ही थ्रेड जानते हैं। नींद (एक्स) अविश्वसनीय है और इसे रद्द नहीं किया जा सकता .... मैं इसे प्लेग की तरह टालना चाहता हूं।

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