2010-06-05 22 views
8

एक बहु-थ्रेडेड WPF अनुप्रयोग में, यह not possible है जो ObservableCollection को WPF विंडो थ्रेड के अलावा किसी अन्य थ्रेड से अपडेट करने के लिए है।एक अलग थ्रेड से अवलोकन करने योग्य चयन को अपडेट करना क्यों संभव नहीं है?

मैं there are workarounds जानते हैं, इसलिए मेरे सवाल "यह CollectionView के प्रकार के एक धागा डिस्पैचर धागा से अलग से अपनी SourceCollection में परिवर्तन का समर्थन नहीं करता" अपवाद से बचने के लिए कैसे नहीं है।

मेरा प्रश्न है, ऐसा अपवाद क्यों है? किसी भी धागे से संग्रह अद्यतनों को अनुमति देना क्यों संभव नहीं था?

व्यक्तिगत रूप से, मुझे ObservableCollection अन्य धागे से बदलते समय UI अद्यतन को अवरुद्ध करने का कोई कारण नहीं दिखता है। यदि दो धागे (समानांतर समेत) एक ही वस्तु तक पहुंच रहे हैं, तो घटनाओं के माध्यम से ऑब्जेक्ट गुणों में परिवर्तन के लिए एक सुनना, दूसरा परिवर्तन कर रहा है, यह हमेशा काम करेगा, कम से कम अगर ताले ठीक से उपयोग किए जाते हैं। तो, क्या कारण हैं?

+0

.NET 4.5 'ObservableCollection' पर क्रॉस-थ्रेड ऑपरेशंस के साथ मदद करने के लिए कार्यक्षमता जोड़ता है; देखें [मैं वर्कर थ्रेड के माध्यम से एक अवलोकन करने योग्य चयन कैसे अपडेट करूं?] (http://stackoverflow.com/q/2091988/50079) – Jon

+0

निम्न लिंक आज़माएं जो थ्रेड-सुरक्षित समाधान प्रदान करता है जो किसी भी थ्रेड से काम करता है और बाध्य किया जा सकता है एकाधिक यूआई धागे के माध्यम से: http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony

उत्तर

15

पहला ... मुझे आपका दर्द महसूस होता है। Ui धागा प्रतिबंध एक दर्द हो सकता है ...

क्यों आप भी इसे पर बनाया गया था के अलावा किसी अन्य धागा से एक Ui तत्व अद्यतन नहीं कर सकते?

मेरा सवाल है, ऐसे अपवाद क्यों हैं?

संक्षेप में, इतिहास में। विंडोज़ थोड़ी देर के आसपास रहा है और जिस तरह से गुई काम के कुछ हिस्सों को COM और जैसे की तरह प्रौद्योगिकियों में एम्बेड किया गया है .... तो इसे बदलना छोटा नहीं है ... कुछ तोड़ना बहुत आसान होगा। मुझे यकीन है कि कई अन्य मुद्दे हैं ... लेकिन मेरे से किसी से ज्यादा समझदार उन्हें समझाने की आवश्यकता होगी। मेरा मानना ​​है कि डब्ल्यूपीएफ टीम वास्तव में इस प्रतिबंध को हटाना चाहती थी और उन्होंने इस पर बहुत मेहनत की ... अंत में मुझे लगता है कि मूल ओएस परिवर्तनों की संख्या की आवश्यकता नहीं है ... इसलिए वे चूहों पर चले गए।

किसी भी धागे से संग्रह अद्यतनों को अनुमति देना क्यों संभव नहीं था?

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

मुझे पता है कि, कामकाज से जुड़े हैं तो मेरे सवाल अपवाद "यह CollectionView के प्रकार के एक धागा डिस्पैचर धागे से अलग से अपनी SourceCollection के लिए नहीं समर्थन परिवर्तन करता है" से बचने के लिए कैसे नहीं है।

कोई कामकाज नहीं है ... काम करने के लिए कुछ भी नहीं है। ObservableCollection टूटा हुआ है .. यह सिर्फ धागा-सुरक्षित नहीं है। आपको इसे बनाना होगा, या उस तक पहुंच, थ्रेड-सुरक्षित होना चाहिए। यह किसी भी चीज के लिए समान है जो थ्रेड-सुरक्षित नहीं है ... यदि आपको इसे थ्रेड-सुरक्षित होने की आवश्यकता है तो इसे बनाएं। यदि आप धागे का उपयोग कर रहे हैं तो आप ताले के बारे में जानते हैं और ऐसे ... उनका उपयोग करें..यह वही है जो वे हैं।

... ब्लॉक यूआई अद्यतन जब ObservableCollection अन्य धागे से बदल गया है .... यह हमेशा काम करेंगे, ताले ठीक से उपयोग किया जाता है कम से कम अगर ....

हैं ताले ठीक से उपयोग किया जाता है ... बिल्कुल! फिर, माइक्रोसॉफ्ट इन ताले लगा सकता था लेकिन उन्होंने बहुत अच्छे कारणों से नहीं किया। आप ताले डाल सकते हैं या आप अन्य रणनीतियों का उपयोग करते हैं जो आपको थ्रेड-सुरक्षित पहुंच प्रदान करेंगे .... बहुत सारे विकल्प।

Task Parallel Library में .net4.0 इन समस्याओं को हल करने के लिए कुछ नए टूल प्रदान करता है। किसी कार्य के लिए एक संदर्भ सेट करने में सक्षम होने के नाते या एक धागा विशेष रूप से उपयोगी है ...

// get the Ui thread context 
    _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

    Action DoInBackground = new Action(() => 
    { 
    /*...In the background... 
     ...process some data for an ObservableCollection...*/ 
    }); 

    Action DoOnUiThread = new Action(() => 
    { 
    /*...On the UI thread... 
     ...read/write data to an ObservableCollection...*/ 
    }); 

    // start the background task 
    var t1 = Task.Factory.StartNew(() => DoInBackground()); 
    // when t1 is done run t1..on the Ui thread. 
    var t2 = t1.ContinueWith(t => DoOnUiThread(), _uiScheduler); 

कुछ को हल करने के लिए के रूप में UI तत्व का धागा आत्मीयता आवश्यकताओं के बारे में मत सोचो .... यह सिर्फ है जिस तरह से यह काम करता है।

सी # और नेट के पास कई टूल्स हैं जिनका उपयोग आप थ्रेडिंग को थोड़ा सा दुःस्वप्न बनाने के लिए कर सकते हैं। उनका प्रयोग करें ... वे मजेदार हो सकते हैं।

मैं धूम्रपान करने जा रहा हूं।

10

यदि आपका संग्रह उपयोगकर्ता इंटरफ़ेस तत्वों के लिए बाध्य है, तो वे उपयोगकर्ता इंटरफ़ेस तत्व संग्रह के CollectionChanged ईवेंट पर सुन रहे हैं, और यह ईवेंट थ्रेड पर उठाया गया है, जिस पर आप संग्रह अपडेट कर रहे हैं।

तो समस्या उपयोगकर्ता इंटरफ़ेस तत्वों के साथ है, जिसे केवल थ्रेड से एक्सेस किया जा सकता है, जिस पर वे बनाए गए थे, न कि संग्रह के साथ।

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