2010-02-10 23 views
6

ठीक है यह वास्तव में सरल हो सकता है लेकिन मैं जो कुछ भी कोशिश करता हूं वह सिर्फ ईंट की दीवार पर लग रहा है।डब्ल्यूपीएफ डिस्पैचर, पृष्ठभूमि कार्यकर्ता और दर्द का एक बहुत सारे दर्द

मैं दो गुण है, जो मेरी WPF फार्म के लिए बाध्य कर रहे हैं के साथ एक दृश्य मॉडल है:

bool IsWorking {get;set;} 
ObservableCollection<OtherViewModel> PendingItems {get;set;} 

मैं एक विधि है कि मैं दृष्टिकोण से कुछ नए लंबित आइटम लाने में फोन है, हालांकि मैं भी क्या दिखाने के लिए फॉर्म (प्रगति पट्टी कताई) पर कुछ प्रकार की प्रगति, प्रगति पट्टी दृश्यता ViewModel पर IsWorking प्रॉपर्टी के लिए बाध्य है, और एक ग्रिड लंबित छवि संग्रह से जुड़ा हुआ है।

मैं IsWorking को सत्य में सेट करने में सक्षम होना चाहता हूं ताकि यूआई प्रगति पट्टी दिखा सके, पृष्ठभूमि में काम चला सके और फिर समाप्त होने के बाद IsWorking को गलत पर सेट कर दें ताकि प्रगति पट्टी दूर हो जाए।

मैं इस तरह एक backgroudworker कुछ बनाया:

 worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
     worker.RunWorkerAsync(); 

अब worker_DoWork विधि है कि एक लंबित आइटम को हासिल करेगा के लिए चला जाता है और उन्हें PendingItems संग्रह करने के लिए कहते हैं कहता है, सब कुछ चलाता है पृष्ठभूमि में यूआई अभी भी उत्तरदायी है लेकिन संग्रह में जोड़ने का प्रयास करते समय मुझे सामान्य क्रॉस थ्रेडेड त्रुटि मिलती है। मैंने कोड को लपेट लिया जो एक प्रेषक कॉल में संग्रह को बदलता है:

 // Update to show the status dialog. 
     Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render, 
          new Action(delegate() 
          { 
           this.PendingItems.Add(\\Blah); 
          }) 
         ); 

लेकिन यह अभी भी वही क्रॉस थ्रेड त्रुटि फेंकता है।

मैं थ्रेडिंग के साथ बहुत अच्छा नहीं हूं इसलिए मुझे नहीं पता कि मैं क्या गलत कर रहा हूं, क्या कोई मुझे इस के साथ हाथ देने में सक्षम होगा?

उत्तर

5

अन्य लोगों ने थ्रेड सुरक्षित अवलोकन संग्रह (ताकि आपको नहीं करना है) के बारे में जानकारी के लिए here पर एक नज़र डालें।

+0

आपका बहुत-बहुत काम करता है महान धन्यवाद है। –

+0

दूसरा लिंक मर चुका है। कोई विचार? – brumScouse

+0

@brumScouse इसे आजमाएं –

4

चूंकि संग्रह को अद्यतन करने के लिए कोड को पृष्ठभूमि थ्रेड से कॉल किया जा रहा है, Dispatcher.CurrentDispatcher गलत प्रेषक है। आपको यूआई के प्रेषक का संदर्भ रखना होगा और अद्यतन को शेड्यूल करते समय उस प्रेषक का उपयोग करना होगा।

0

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher के अनुसार, क्योंकि आप नए थ्रेड (कार्यकर्ता द्वारा बनाए गए) में Dispatcher.CurrentDispatcher को कॉल करते हैं, यह नया प्रेषक ऑब्जेक्ट बनाता है। तो आपको किसी भी तरह से कॉलिंग थ्रेड (ui धागा) से प्रेषक प्राप्त करना चाहिए। एक अन्य विकल्प तर्क के रूप में worker.RunWorkerAsync (वस्तु तर्क) को ui डिस्पैचर पारित करने के लिए

worker = new BackgroundWorker(); 
worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
worker.RunWorkerAsync(Dispatcher.CurrentDispatcher); 

... 

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Dispatcher dispatcher = e.Argument as Dispatcher; // this is right ui dispatcher 

    // Update to show the status dialog. 
    dispatcher.Invoke(DispatcherPriority.Render, 
          new Action(delegate() 
          { 
           this.PendingItems.Add(\\Blah); 
          }) 
         ); 

}