2011-03-07 19 views
7

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

मेरे पास एक कार्यकर्ता भी है जो अपने कोड में डिस्पैचर का उपयोग करने से बचाता है। मैंने उन कारणों से पूछा लेकिन उनका जवाब मुझे संतुष्ट नहीं करता था। उन्होंने कहा, उन्हें एक वर्ग में छुपा "जादू" पसंद नहीं है।

वैसे मैं निम्नलिखित वर्ग का प्रशंसक हूं।


public class BindingBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private Dispatcher Dispatcher 
    { 
#if SILVERLIGHT 
     get { return Deployment.Current.Dispatcher; } 
#else 
     get { return Application.Current.Dispatcher; } 
#endif 
    } 

    protected void RaisePropertyChanged<T>(Expression<Func<T>> expr) 
    { 
     var memberExpr = (MemberExpression)expr.Body; 
     string property = memberExpr.Member.Name; 

     var propertyChanged = PropertyChanged; 
     if (propertyChanged == null) return; 

     if (Dispatcher.CheckAccess()) 
     propertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); 
     else 
     Dispatcher.BeginInvoke(() => RaisePropertyChanged(expr)); 
    } 
} 

यहां सवाल है। क्या कोई कारण है कि कुछ लोग ऐसी कक्षा का उपयोग नहीं करना चाहते हैं? शायद मुझे इस दृष्टिकोण पर पुनर्विचार करना होगा।

आपको स्वीकार करना होगा, एक अजीब चीज है। Dispatcher.CheckAccess() इंटेलिसेंस से बाहर रखा गया है। शायद इस तथ्य के कारण वे थोड़ी डरावनी हैं।

सादर

संपादित करें:

ठीक है, एक और उदाहरण। एक जटिल वस्तु पर विचार करें। उदाहरण के रूप में संग्रह शायद सबसे अच्छा विचार नहीं था।


public class ExampleVm : BindingBase 
{ 
    private BigFatObject _someData; 
    public BigFatObject SomeData 
    { 
     get { return _someData; } 
     set 
     { 
     _someData = value; 
     RaisePropertyChanged(() => SomeData); 
     } 
    } 

    public ExampleVm() 
    { 
     new Action(LoadSomeData).BeginInvoke(null, null); //I know - it's quick and dirty 
    } 

    private void LoadSomeData() 
    { 
     // loading some data from somewhere ... 
     // result is of type BigFatObject 

     SomeData = result; // This would not work without the Dispatcher, would it? 
    } 
} 

उत्तर

5

मैं भी हूँ, व्यक्तिगत रूप से, दृश्य मॉडल कक्षाओं में Dispatcher के खिलाफ नहीं। मैंने इसके साथ कोई महत्वपूर्ण समस्या नहीं देखी है, फिर भी यह आपके कोड के लिए सबसे लचीलापन देता है।

लेकिन मुझे जितना संभव हो सके बुनियादी ढांचे कोड में Dispatcher के उपयोग को समाहित करने का विचार पसंद है। जैसे आपने RaisePropertyChanged विधि (बीटीडब्लू, RaisePropertyChanged के मामले में किया था, आपको कुछ भी प्रेषण करने की आवश्यकता नहीं है - बाध्यकारी पहले से ही आपके लिए करता है; आपको केवल संग्रह में परिवर्तन भेजना होगा)।

सबसे बड़ा और एकमात्र नुकसान जो मैं यहां देखता हूं वह इकाई परीक्षण है। जब आप अपने तर्क का परीक्षण करने का प्रयास करते हैं तो चीजें मुश्किल हो सकती हैं जिसमें Dispatcher का उपयोग शामिल है। कल्पना कीजिए कि आप एक दृश्य के मॉडल में इस तरह कोड कुछ था:

private void UpdateMyCollection() 
{ 
    IList<ModelData> dataItems = DataService.GetItems(); 

    // Update data on UI 
    Dispatcher.BeginInvoke(new Action(() => { 
     foreach (ModelData dataItem in dataItems) 
     { 
     MyObservableCollection.Add(new DataItemViewModel(dataItem)); 
     } 
    })); 
} 

कोड इस तरह की काफी ठेठ जब यह एक गैर यूआई धागे से संग्रह को अद्यतन करने के लिए आता है। अब, आप एक यूनिट टेस्ट कैसे लिखेंगे जो अवलोकन संग्रह में आइटम जोड़ने के तर्क का परीक्षण करता है? सबसे पहले, आपको Dispatcher संपत्ति का नकल करने की आवश्यकता होगी क्योंकि Application.Currentnull इकाई परीक्षण निष्पादन के दौरान है। सबसे दूसरा, आप इसे कैसे मजाक करेंगे? क्या आप एक विशेष थ्रेड बनायेंगे जो यूआई थ्रेड की नकल करेगा और उस थ्रेड के का उपयोग करेगा? तो, इस तरह की चीजें।

नीचे की रेखा यह है कि यदि आप चाहते हैं कि आपका कोड यूनिट-टेस्ट-फ्रेंडली हो, तो आपको इस बारे में सोचना होगा कि आप Dispatcher पर नकल कैसे करेंगे। यह एकमात्र चिंता है।

अद्यतन:

दूसरे उदाहरण आप Dispatcher के बिना काम करेंगे प्रदान की (बाध्यकारी चाल करना होगा)।

+0

"(बीटीडब्ल्यू, राइजप्रोपर्टी के मामले में आपको कुछ भी प्रेषण करने की आवश्यकता नहीं है - बाध्यकारी पहले से ही आपके लिए यह करता है; आपको केवल संग्रह में परिवर्तन भेजना होगा)" ठीक है अगर यह सच है तो नेट से कुछ बदल दिया गया है 3.5। एक संग्रह पर विचार करें जो एक पृथक धागे में भरा हुआ है और फिर इस थ्रेड द्वारा व्यूमोडेल में एक संपत्ति में पारित किया गया है। मुझे नहीं लगता कि या BackGroundWorker के बिना यह संभव है। – DHN

+0

मुझे समझ में नहीं आता कि यूनिट परीक्षण के दौरान नुकसान क्यों हैं। क्या आप इसे एक और अधिक बता सकते हैं, कृपया? – DHN

+0

@ डीएनएन - यूनिट परीक्षणों के साथ परेशानी के उदाहरण के लिए मेरा अपडेट देखें। जैसा कि "एक पृथक धागे में लोड किया गया संग्रह पर विचार करें और फिर इस थ्रेड द्वारा व्यूमोडेल में एक संपत्ति में पारित किया गया" मैंने स्पष्ट रूप से उल्लेख किया है कि "आपको केवल संग्रह में परिवर्तन भेजना होगा", इसलिए, हाँ, आपको ' डिस्पैचर 'संग्रह को संशोधित करने के लिए, लेकिन सामान्य गुण नहीं (यानी आपको UI थ्रेड पर' INotifyPropertyChanged.PropertyChanged 'ईवेंट नहीं उठाना है, लेकिन आपको यूआई थ्रेड पर 'INotifyCollectionChanged.CollectionChanged' को उठाना होगा)। –

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