2011-12-10 16 views
5

के साथ रून मैं नए एसिंक सीटीपी और एमवीवीएम पैटर्न के साथ खेल रहा हूं। मैं अपने पुराने कार्यक्रम को परिवर्तित कर रहा हूं जो पृष्ठभूमि कार्यकर्ता का उपयोग कर रहा था और मेरे मॉडल में संग्रह को अद्यतन करने के लिए प्रगति की रिपोर्ट करता था। मैं इतनाasync कार्य। एमवीवीएम

TaskEx.Run(async() => 
{ 
    while (true) 
    { 
    // update ObservableCollection here 
    } 
    await TaskEx.Delay(500); 
}); 

मेरे विचार मैं अपने viewmodel करने के लिए बाध्य है जो इस नमूदार संग्रह को उजागर करता है में की तरह कुछ करने के लिए इसे परिवर्तित कर दिया है। हालांकि, जब मेरे संग्रह अद्यतन मुझे निम्नलिखित अपवाद

इस प्रकार का संग्रह दृश्य डिस्पैचर थ्रेड से अलग धागे से अपने स्रोत चयन में परिवर्तनों का समर्थन नहीं करता है।

मुझे यकीन नहीं है कि इस तरह किए जाने पर यूआई थ्रेड पर वापस खींचने का सही तरीका क्या है।

+0

एक तरफ ध्यान दें के रूप में, दृश्य स्टूडियो 11 डेवलपर पूर्वावलोकन है कि आप डाउनलोड कर सकते हैं में 'async' के एक अद्यतन संस्करण है। – svick

उत्तर

5

आपको Task.Run(), या किसी अन्य विशेष माध्यम का उपयोग करके एसिंक विधियों को चलाने की आवश्यकता नहीं है, बस उन्हें कॉल करें। और आपके मामले में, यह वही है जो समस्या पैदा कर रहा है।

इस तरह देखते हुए समारोह:

Action f = async() => 
{ 
    while (true) 
    { 
     // modify the observable collection here 
     await Task.Delay(500); 
    } 
}; 

यूआई धागे पर कुछ विधि रन से इस तरह यह कॉलिंग, एक ईवेंट हैंडलर की तरह: बिल्कुल

f(); 

काम करता है जैसा कि होना चाहिए। यह चक्र के पहले पुनरावृत्ति को निष्पादित करता है और फिर लौटाता है। यूआई थ्रेड पर 500 एमएस (या अधिक, यदि यूआई थ्रेड व्यस्त है) के बाद अगला पुनरावृत्ति निष्पादित किया जाता है।

दूसरी ओर, यदि आप इसे इस तरह कहते हैं:

Task.Run(addNames); 

इसे सही ढंग से काम नहीं करता। इसका कारण यह है कि async विधियां उसी संदर्भ में जारी रखने की कोशिश करती हैं जैसे वे शुरू किए गए थे (जब तक कि आप स्पष्ट रूप से अन्यथा निर्दिष्ट नहीं करते)। पहला संस्करण यूआई थ्रेड पर शुरू किया गया था, इसलिए यह यूआई थ्रेड पर जारी रहा। दूसरा संस्करण थ्रेडपूल थ्रेड पर शुरू हुआ (Task.Run() पर धन्यवाद) और वहां भी जारी रहा। यही कारण है कि यह आपकी त्रुटि का कारण बन गया।

यह सब SynchronizationContext का उपयोग करके किया जाता है, यदि कोई मौजूद है।

3

आपने मुख्य यूआई थ्रेड पर ObservableCollection बनाया है, और इसे एसिंक्रोनस पृष्ठभूमि थ्रेड पर अपडेट करने का प्रयास कर रहे हैं, जिसे आप WPF में नहीं कर सकते हैं।

वैकल्पिक रूप से, पृष्ठभूमि थ्रेड से परिणाम प्राप्त करें, फिर उन्हें मुख्य UI थ्रेड पर ObservableCollection पर जोड़ें।

आम तौर पर एक पृष्ठभूमि धागे पर एक ObservableCollection को अद्यतन करने के कुछ इस तरह दिखेगा के लिए मेरे कोड:

private async void LoadItems() 
{ 
    Task<List<MyItem>> getItemsTask = Task.Factory.StartNew(GetItems); 

    foreach(MyItem item in await getItemsTask) 
     MyCollection.Add(item); 
} 

private List<MyItem> GetItems() 
{ 
    // Make database call to get items 
} 
2

हालांकि यह सच है कि आप एक दूसरे धागे से एक ObservableCollection अद्यतन करने के लिए सक्षम नहीं हैं है, यह संभव है एक अतुल्यकालिक देखने योग्य संग्रह बनाने के लिए। यह आपको संग्रहों के भीतर, या धागे पर संग्रह को अद्यतन करने की अनुमति देता है जहां संग्रह नहीं बनाया गया था।

मैं उदाहरण पोस्ट करूंगा, लेकिन मुझे यहां जानकारी मिली। यह बहुत चालाक है, और मैंने इसे एक बहुत ही उपयोगी उदाहरण पाया।

http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

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