2012-07-10 27 views
14

मुझे लगता है कि मुझे डिस्पैचर कतार समझने में कुछ मदद चाहिए।डिस्पैचर कतार को समझना

जब नया काम आता है तो यह प्रेषक कतार की शुरुआत में जोड़ा जाता है और जब डिस्पैचर एक कार्यरत आइटम को संसाधित करना चाहता है तो इसे शुरुआत से हटा दिया जाता है।

अधिक सामान्य शब्दों में: यदि कोई काम है तो यह कतार के अंदर एक फीफो तरीके से संग्रहीत हो जाता है और तब तक संसाधित नहीं किया जाता है जब तक कोई काम बाकी नहीं होता है।

MSDN प्रलेखीकरण here एक loop और एक frame की चर्चा करते हुए किया जाता है:

The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.

लेकिन जहां इस संदर्भ में एक पाश है? मेरे लिए एक लूप कुछ ऐसा होता है जो किसी चीज़ पर पुनरावृत्त होता है और जब यह अंत तक पहुंच जाता है तो यह फिर से शुरू होता है।

और frame की अवधारणा क्या है? एमएसडीएन दस्तावेज के अनुसार एक फ्रेम कतार के अंदर काम करने वाली वस्तुओं का एक पंच है? यदि यह सच है तो स्थिर विधि Disptatcher.PushFrame() का उपयोग कैसे किया जाना चाहिए?

और सबसे दिलचस्प सवाल यह है कि कतार की वर्तमान स्थिति प्राप्त करने का कोई तरीका है या नहीं, विशेष रूप से कतार में कितनी वस्तुएं हैं।

क्या यह तब होता है जब कोई विधि जिसे पहले (और डिस्पैचर कतार में डालने के लिए) कहा जाता है, उसे निष्पादित किया जाता है कि उसे तुरंत कतार से निकाल दिया जाता है या यह दूसरी अवधि के लिए अंदर रहता है?

मुझे पता है, :-)

+1

पहला प्रश्न: क्यों? आप डिस्पैचर के साथ कुछ भी क्यों चाहते हैं? आम तौर पर, एक डब्ल्यूपीएफ प्रक्रिया के लिए डिस्पैचर बस "संदेश पंप" होता है। यह सभी संदेशों/घटनाओं/आदेशों को WPF UI के माध्यम से एप्लिकेशन कोड (जैसे माउस मूवमेंट, क्लिक इत्यादि) के माध्यम से संभालता है। जब अनुप्रयोग रन विधि लागू होती है, तो वह उस लूप को शुरू करने के लिए पुशफ्रेम को कॉल करता है। आप एक ही धागे के लिए एक और शुरू नहीं कर सकते हैं; और डिस्पैचर यूआई काम को संसाधित करने के लिए है। –

+2

क्या आपने [थ्रेडिंग मॉडल] (http://msdn.microsoft.com/en-us/library/ms741870.aspx) के बारे में पढ़ा था? –

+1

यह निर्माता-उपभोक्ता समस्या का एक मानक समाधान है: http://en.wikipedia.org/wiki/Producer-consumer_problem –

उत्तर

22

तो कई सवाल बहुत कम Dispatcher आसपास के प्रलेखन है, तो आप थोड़ा के आसपास एकत्रित न करने के लिए अंदरूनी कामकाज के बारे में पता करना होगा।

एक प्रेषक मूल रूप से ऐसा कुछ है जो एप्लिकेशन के Message Pump के आसपास काम करता है। प्रश्न में से एक windows message loop के शीर्ष पर बैठता है।

परिणामस्वरूप, केवल एक आवेदन डिस्पैचर हो सकता है - वैश्विक प्रेषक ऑब्जेक्ट Application.Current.Dispatcher तक पहुंच योग्य है। अन्य प्रेषकों Dispatcher.CurrentDispatcher तक पहुँचने, जो प्रलेखन

के अनुसार धागा वर्तमान में क्रियान्वित करने के लिए डिस्पैचर हो जाता है और अगर एक पहले से ही धागा साथ संबद्ध नहीं है एक नई डिस्पैचर बनाता है के द्वारा ही संभव है।

हालांकि, इस नए प्रेषक पर Run को कॉल करना अवरुद्ध हो जाएगा।

जब आप Dispatcher.PushFrame करते हैं, तो यह मूल रूप से वर्तमान प्रेषक पर एक फ्रेम को धक्का देता है। DispatcherObject जैसे DispatcherFrame से प्राप्त कुछ भी इसके प्रेषक को वर्तमान में सेट किया जाएगा। हम इसे अपने कन्स्ट्रक्टर को देखकर सत्यापित कर सकते हैं।

private Dispatcher _dispatcher; 

protected DispatcherObject() 
{ 
    this._dispatcher = Dispatcher.CurrentDispatcher; 
} 
बेशक

, एक साधारण घटना पाश होने पर्याप्त नहीं है - जब आप अन्य काम के लिए मजबूर करने के लिए वर्तमान घटना पाश किया जाना नष्ट करने की जरूरत है बार कर रहे हैं। और यही कारण है कि आपके पास DispatcherFrame है।यह वास्तव में घटना लूप का गठन करता है। जब आप डिस्पैचर में एक फ्रेम धक्का, तो ऐसा होता है:

while (frame.Continue) 
     { 
      if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0)) 
      { 
       break; 
      } 
      this.TranslateAndDispatchMessage(ref msg); 
     } 

के बाद संदेश बाहर ले जाया जाता है यह, TranslateAndDispatchMessage कि डिस्पैचर में प्राथमिकता के आधार पर कतार में मूल्यांकन किया जाता है।

यदि किसी ऑपरेशन को प्रेषक पर चलाने के लिए लंबा समय लगता है, तो यह अस्थायी रूप से ईवेंट लूप को रोकता है और क्योंकि यह सिग्नलिंग का जवाब नहीं देता है, तो ऐसा लगता है कि एप्लिकेशन प्रत्युत्तर देना बंद कर देता है।

Here's an article जो घटना पाश जल्द ही चलने की अनुमति देकर प्रतिक्रिया करने के लिए यूआई के लिए मजबूर करने के लिए एक फ्रेम का उपयोग करता है।

कतार पहुँचने के लिए के रूप में, के रूप में यह है, वहाँ कोई रास्ता नहीं डिस्पैचर के बाहर कतार के राज्य पता करने के लिए है। यह एक आंतरिक विवरण है, और यह उचित है कि यह खुलासा नहीं है।

+1

आपके विस्तृत उत्तर (और देरी के लिए खेद है) के लिए बहुत बहुत धन्यवाद –

+1

@Marc कोई समस्या नहीं। :) – Asti

+6

_ "नतीजतन, प्रति एप्लिकेशन केवल एक डिस्पैचर ही हो सकता है।" _। <= यह सच नहीं है, प्रेषक उदाहरण थ्रेड पर बाध्य होंगे। Dispatcher.CurrentDispatcher का सारांश देखें: _ "वर्तमान में निष्पादित धागे के लिए प्राप्त करता है और कोई नया बनाता है यदि कोई पहले से ही थ्रेड से जुड़ा हुआ नहीं है।" _ आप डिस्पैचर को संदेशपंप के विस्तार के रूप में कल्पना कर सकते हैं, एक्सटेंशन निष्पादित करने में सक्षम बनाता है केवल संदेश कोड को संभालने के बजाय प्रतिनिधियों। –