2012-07-08 14 views
10

(निम्न आइटम विभिन्न लक्ष्यों है, लेकिन im दिलचस्प जानने कि वे किस तरह "रोका गया")Thread.sleep बनाम मॉनिटर। वैट बनाम पंजीकृत WaitHandle?

सवाल

Thread.sleep - यह एक सिस्टम पर प्रदर्शन को प्रभावित करता है वह अपने प्रतीक्षा के साथ एक धागा बाँध करता है? ?

Monitor.Wait के बारे में क्या? जिस तरह से वे "प्रतीक्षा" करते हैं, उसमें क्या अंतर है? क्या वे अपने इंतजार के साथ एक थ्रेड बांधते हैं?

RegisteredWaitHandle के बारे में क्या? यह विधि एक प्रतिनिधि को स्वीकार करती है जिसे निष्पादित किया जाता है जब प्रतीक्षा संभाल संकेत दिया जाता है। जबकि यह प्रतीक्षा कर रहा है, यह धागा बांधता नहीं है।

तो कुछ थ्रेड रुक गए हैं और एक प्रतिनिधि द्वारा जागृत किया जा सकता है, जबकि अन्य बस प्रतीक्षा करें? स्पिन?

क्या कोई चीजों को स्पष्ट कर सकता है?

संपादित

http://www.albahari.com/threading/part2.aspx

enter image description here

उत्तर

8

दोनों Thread.Sleep और Monitor.Waitthe WaitSleepJoin state में धागा डाल:

WaitSleepJoin: धागा अवरुद्ध है। यह थ्रेड :: नींद बुला या धागा :: में शामिल हों, एक ताला अनुरोध के का नतीजा हो सकता है - उदाहरण के लिए, से बुला मॉनिटर :: दर्ज करें या मॉनिटर :: प्रतीक्षा करें - या इस तरह के रूप में एक धागा तुल्यकालन वस्तु पर इंतजार कर के ManualResetEvent।

RegisteredWaitHandleRegisterWaitForSingleObject कॉल करके और WaitHandle पास करके प्राप्त की है। आम तौर पर इस वर्ग के उपयोग के सभी सन्तान तंत्र अवरुद्ध है, तो बुला Wait फिर WaitSleepJoin (जैसे AutoResetEvent) में धागा डाल देंगे।

यहाँ MSDN से एक और उद्धरण है:

RegisterWaitForSingleObject विधि निर्दिष्ट ऑब्जेक्ट की WaitHandle की वर्तमान स्थिति की जांच करता है। यदि ऑब्जेक्ट की स्थिति बेकार है, विधि एक प्रतीक्षा ऑपरेशन पंजीकृत करता है। थ्रेड पूल से थ्रेड द्वारा प्रतीक्षा ऑपरेशन किया जाता है। प्रतिनिधि एक कार्यकर्ता धागा द्वारा निष्पादित जब वस्तु के राज्य का संकेत या टाइम-आउट अंतराल समाप्त होने के हो जाता है।

तो पूल में एक धागा संकेत के लिए प्रतीक्षा करता है।

+0

रजिस्ट्रार WaitHandle –

+0

@Royi Namir के बारे में क्या: मेरा संपादन देखें। – Tudor

+0

मुझे नहीं लगता कि आप सही हैं 'रजिस्ट्रार वाइटहैंडल': कृपया मेरा संपादन देखें। –

3

ThreadPool.g RegisterWaitForSingleObject इसके मूल कार्यान्वयन में अंततः QueueUserAPC पर कॉल करता है। रोटर स्रोत देखें (sscli20 \ clr \ src \ वी एम \ win32threadpool.cpp (1981))। अपने धागा Thread.Sleep प्रतीक्षा के विपरीत एक पड़ाव है जब आप RegisterWaitForSingleObject उपयोग करने के लिए डाल नहीं किया जाएगा।

इसके बजाय इस सूत्र उपयोगकर्ता मोड कॉलबैक के साथ एक फीफो कतार पंजीकृत किया गया है जो जब धागा एक alertable अवस्था में है बुलाया जाएगा के लिए

। इसका मतलब है कि आप काम करना जारी रख सकते हैं और जब आपका धागा अवरुद्ध हो जाता है तो ओएस पंजीकृत कॉलबैक पर काम करेगा, जिससे आपका धागा इंतजार कर रहा है जबकि कुछ सार्थक करने का मौका देता है।

Edit1:

विश्लेषण पूरा करने के लिए। थ्रेड पर जिसने RegisterWaitForSingleObject को कॉल किया था, कॉलबैक को थ्रेड पर कॉल किया जाता है जब यह एक सतर्क स्थिति में होता है। एक बार ऐसा होने पर थ्रेड जो रजिस्टर किया गया है RegisterWaitForSingleObject एक सीएलआर कॉलबैक निष्पादित करेगा जो एक अन्य कॉलबैक पंजीकृत करता है जिसे थ्रेड पूल कॉलबैक प्रतीक्षा थ्रेड द्वारा संसाधित किया जाता है जो सिग्नल कॉलबैक के लिए प्रतीक्षा करने के लिए केवल वहां होता है। यह थ्रेड पूल कॉलबैक प्रतीक्षा थ्रेड तब संकेतित कॉलबैक के लिए नियमित अंतराल में जांच करेगा।

यह इंतजार धागा अंत में QueueUserWorkItem फोन के लिए संकेत कॉलबैक एक धागा पूल धागे पर निष्पादित किया जाना है। विभिन्न स्तरों पर

+0

पूल में एक धागा 'RegisterWaitForSingleObject' के प्रलेखन में जो मैंने समझा, उससे वास्तव में हैंडल को संकेतित करने की प्रतीक्षा की जाएगी, लेकिन जरूरी नहीं कि वह थ्रेड जो वास्तव में काम करता है। – Tudor

+0

हाँ आप सही हैं। पूर्ण विश्लेषण के लिए मेरा संपादन देखें। –

+0

इसलिए यदि मैं 50 बार पंजीकृत WaitHandle निष्पादित करता हूं, तो अभी भी एक "चेकिंग थ्रेड" होगा जो हमेशा सिग्नल स्थिति की जांच करेगा, लेकिन अन्य एन -1 थ्रेड पूल थ्रेड, काम करने से मुक्त हैं, है ना? –

3

Thread.Sleep और RegisteredWaitHandle काम करते हैं। मुझे कोशिश करते हैं और इसे सुलझाने करते हैं:

प्रक्रियाओं से अधिक थ्रेड, जो एक साथ निष्पादित (ओएस अनुसूचक के आधार पर) की है। यदि कोई थ्रेड Thread.Sleep या Monitor.Wait पर कॉल करता है, तो यह स्पिन नहीं करता है - इसे WaitSleepJoin स्थिति में रखा जाता है, और सीपीयू अन्य धागे को दिया जाता है।

अब, जब आपके पास कई एक साथ काम करने वाले आइटम होते हैं, तो आप एक थ्रेड पूल का उपयोग करते हैं - एक तंत्र जो कई धागे बनाता है, और अपने धागे को कॉल भेजने के लिए कार्य वस्तुओं की अपनी समझ का उपयोग करता है। इस मॉडल में, वर्क थ्रेड को थ्रेड पूल डिस्पैचर से कुछ काम करने के लिए कहा जाता है, और फिर पूल पर वापस लौटें। यदि कोई कार्यकर्ता थ्रेड ब्लॉकिंग ऑपरेशन को कॉल करता है - जैसे Thread.Sleep या Monitor.Wait - यह धागा "बंधे" है, क्योंकि थ्रेड पूल प्रेषक अतिरिक्त कार्य आइटमों के लिए इसका उपयोग नहीं कर सकता है।

मैं वास्तविक एपीआई से परिचित नहीं हूँ, लेकिन मुझे लगता है कि RegisteredWaitHandle जब जरूरत थ्रेड पूल डिस्पैचर बता एक कार्यकर्ता धागा कॉल करने के लिए होगा - और अपने खुद के धागा नहीं "करार" है, और उसके काम या वापसी जारी रख सकते हैं थ्रेड पूल में।

6

ThreadPool.RegisterWaitForSingleObject के संबंध में, यह प्रति पंजीकरण (पूल या अन्यथा) धागा बांधता है। आप आसानी से इस परीक्षण कर सकते हैं: जो कहता है LINQPad में निम्न स्क्रिप्ट चलने वाले विधि 20,000 बार:

static ManualResetEvent _starter = new ManualResetEvent (false); 

void Main() 
{ 
    var regs = Enumerable.Range (0, 20000) 
     .Select (_ => ThreadPool.RegisterWaitForSingleObject (_starter, Go, "Some Data", -1, true)) 
     .ToArray(); 

    Thread.Sleep (5000); 
    Console.WriteLine ("Signaling worker..."); 
    _starter.Set(); 
    Console.ReadLine(); 

    foreach (var reg in regs) reg.Unregister (_starter); 
} 

public static void Go (object data, bool timedOut) 
{ 
    Console.WriteLine ("Started - " + data); 
    // Perform task... 
} 

कि कोड 5 सेकंड की अवधि "प्रतीक्षा" के लिए करार 20,000 धागे हैं, तो यह संभवतः नहीं कर सका काम।

संपादित - के जवाब में:

"इस बात का सबूत है, लेकिन अभी भी किसी एकल थ्रेड जो केवल संकेत के लिए जाँच करता है थ्रेड पूल में।?"

यह एक कार्यान्वयन विस्तार है। हां, यह को एक थ्रेड के साथ कार्यान्वित किया जा सकता है जो प्रबंधित थ्रेड पूल में कॉलबैक को ऑफ़लोड करता है, हालांकि इसकी कोई गारंटी नहीं है। प्रतीक्षा करें हैंडल अंततः ऑपरेटिंग सिस्टम द्वारा प्रबंधित की जाती हैं, जो कॉलबैक को भी ट्रिगर करने की संभावना है।यह अपने आंतरिक कार्यान्वयन में एक थ्रेड (या धागे की एक छोटी संख्या) का उपयोग कर सकता है। या इंटरप्ट्स के साथ, यह एक थ्रेड को अवरुद्ध नहीं कर सकता है। यह ऑपरेटिंग सिस्टम संस्करण के हिसाब से भी भिन्न हो सकता है। यह एक कार्यान्वयन विस्तार है जो हमारे लिए कोई वास्तविक प्रासंगिकता नहीं है।

+0

thnaks। यह एक सबूत है। लेकिन क्या अभी भी एक धागा है जो सिग्नल के लिए जांच करता है? थ्रेड पूल में? –

+0

प्रतिक्रिया –

3

हालांकि यह सच है RegisterWaitForSingleObject प्रतीक्षा धागे बनाता है, हर कॉल एक बनाता है नहीं।

MSDN से

:

न्यू प्रतीक्षा धागे स्वचालित रूप से जब

आवश्यक रेमंड चेन के blog से बनाई गई हैं:

... बजाय एक पूरी धागा की लागत के लिए, यह लागत कुछ थ्रेड के 1/64 के करीब (लेकिन बिल्कुल नहीं)

तो RegisterWaitForSingleObject का उपयोग करना आम तौर पर अपने स्वयं के प्रतीक्षा धागे बनाने के लिए बेहतर है।

+0

HI, (ma kore?) के लिए संपादित करें, इसलिए RegisterWaitForSingleObject बनाना प्रतीक्षा थ्रेड बना रहा है, लेकिन हम नहीं जानते कि कितने? तो आपको लगता है कि थ्रेड पूल में एक सिंगल थ्रेड नहीं है जो सिग्नलिंग स्थिति की जांच करता है? और इसका मतलब क्या है धागा का 1/64? इसका एक अंश .... कृपया –

+0

समझाएं जैसा कि रेमंड बताते हैं, यह 'WaitForMultipleObjects' का उपयोग करता है, इसलिए एक से अधिक प्रतीक्षा थ्रेड का उपयोग एक से अधिक ऑब्जेक्ट (64 तक) के लिए किया जाता है। –

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