2011-01-07 20 views
15

में यूआई डिस्पैचर तो एक एमवीवीएम पर्यावरण में कहें, मैं पृष्ठभूमि थ्रेड में हूं और मैं यूई नियंत्रण पर एक अद्यतन चलाने के लिए चाहता हूं। तो आम तौर पर मैं अपने बटन पर जाऊंगा। डिस्पैचर.बिनजिन इनवोक (ब्लब्ला) लेकिन मेरे पास myButton तक पहुंच नहीं है (क्योंकि व्यूमोडेल के पास दृश्य के नियंत्रण तक पहुंच नहीं है)। तो ऐसा करने के लिए सामान्य पैटर्न क्या है?डब्ल्यूपीएफ/मल्टीथ्रेडिंग: एमवीवीएम

(मुझे लगता है कि वहाँ हमेशा बाध्यकारी है, लेकिन मुझे पता है कि कैसे डिस्पैचर के माध्यम से यह करना चाहते हैं)

+2

http://stackoverflow.com/questions/486758/is-wpf-dispatcher-the-solution-of-multi-threading-problems का डुप्लिकेट? –

+0

डुप्लिकेट नहीं है ... वह पूछ रहा है कि व्यूमोडेल द्वारा लॉन्च किए गए पृष्ठभूमि थ्रेड से प्रेषक कैसे प्राप्त करें (जिसे आमतौर पर प्रेषक तक पहुंच नहीं है)। –

उत्तर

36

की तरह उपयोग कर सकते हैं मैं आमतौर पर Application.Current.Dispatcher का उपयोग करें:: के बाद से Application.Current है

+7

और आप एप्लिकेशन ऑब्जेक्ट के बिना अपने व्यू मॉडल का परीक्षण कैसे करेंगे? –

+2

@ गीर्ट वैन होरिक आप अपने दृश्य मॉडल परीक्षण इकाई के लिए एप्लिकेशन ऑब्जेक्ट का नकल कर सकते हैं। नेक्रो टिप्पणी के लिए खेद है - मैंने मल्टीथ्रेड प्रोग्रामिंग के लिए एक वैध एमवीवीएम समाधान की खोज करते समय इस SO लेख पर ठोकर खाई। – SRM

0

आप अपने दृश्य मॉडल पर एक घटना बढ़ा सकता है (शायद वह जा रहा है इंगित करने के लिए एक नामकरण परंपरा का उपयोग कर एक गैर-यूआई थ्रेड से उठाया जाना चाहिए - उदाहरण के लिए NotifyProgressChangedAsync)। फिर आपका दृश्य जो घटना से जुड़ा हुआ है, प्रेषक से उचित तरीके से निपट सकता है।

या, आप अपने व्यू मॉडल (आपके दृश्य से) में एक सिंक्रनाइज़िंग फ़ंक्शन में एक प्रतिनिधि को पास कर सकते हैं।

public static class Execute 
{ 
    private static Action<System.Action> executor = action => action(); 

    /// <summary> 
    /// Initializes the framework using the current dispatcher. 
    /// </summary> 
    public static void InitializeWithDispatcher() 
    { 
#if SILVERLIGHT 
     var dispatcher = Deployment.Current.Dispatcher; 
#else 
     var dispatcher = Dispatcher.CurrentDispatcher; 
#endif 
     executor = action =>{ 
      if(dispatcher.CheckAccess()) 
       action(); 
      else dispatcher.BeginInvoke(action); 
     }; 
    } 

    /// <summary> 
    /// Executes the action on the UI thread. 
    /// </summary> 
    /// <param name="action">The action to execute.</param> 
    public static void OnUIThread(this System.Action action) 
    { 
     executor(action); 
    } 
} 

यह उपयोग करने से पहले आप यूआई धागे से Execute.InitializeWithDispatcher() फोन करना होगा तो आप इस Execute.OnUIThread(()=>SomeMethod())

13

Caliburn Micro स्रोत कोड से स्थैतिक, आपको नियंत्रण के संदर्भ की आवश्यकता नहीं है

+0

अगर मैं Dispatcher.CurrentDispatcher का उपयोग करता हूं तो मुझे अभी भी त्रुटि मिलती है। यदि मैं एप्लिकेशन का उपयोग करता हूं तो यह सही तरीके से काम करता है। वर्तमान। डिस्पैचर। –

0

यूआई थ्रेड के प्रेषक को व्यूमोडेल के कन्स्ट्रक्टर को पास करें और उसे वीएम में स्टोर करें।

ध्यान दें कि प्रत्येक धागे का अपना प्रेषक हो सकता है। आपको यूआई थ्रेड की आवश्यकता होगी!

4

Catel के व्यूमोडेलबेस में एक डिस्पैचर प्रॉपर्टी है जिसका आप उपयोग कर सकते हैं।

+0

DispatcherHelper क्लास में GetCurrentDispatcher विधि।https://catel.codeplex.com/SourceControl/latest#src/Catel.MVVM/Catel.MVVM.NET40/Windows/Threading/Helpers/Dispatcherhelper.cs –

4

मैं करते हैं मेरी ViewModels DependencyObject से विरासत है और सुनिश्चित करें कि वे यूआई धागा है, जो उन्हें पूरी तरह से इस स्थिति से निपटने के poises पर निर्माण कर रहे हैं करने के लिए - वे एक Dispatcher संपत्ति है कि यूआई धागा के डिस्पैचर से मेल खाती है है। फिर, आपको ViewModel के कार्यान्वयन विवरण के साथ अपने विचार को प्रदूषित करने की आवश्यकता नहीं है।

कुछ अन्य प्लस:

  • यूनिट testability: आप कर सकते हैं इकाई परीक्षण इन एक में चल रहे एप्लिकेशन के बिना ViewModel
  • देखें & के बीच
  • ढीला युग्मन आप निर्भरता गुण परिभाषित कर सकते हैं (बल्कि Application.Current.Dispatcher पर भरोसा करने की बजाय) अपने व्यूमोडेल पर और दृश्य को अपडेट करने के लिए कोई कोड नहीं लिखें क्योंकि वे गुण बदलते हैं।