मैं पृष्ठभूमि में डेटा को लोड करने की अनुमति देने के लिए एक विंडोज़ फॉर्म संशोधित कर रहा हूं जबकि UI उत्तरदायी बना रहता है। डेटा को पुनः प्राप्त करने और बांधने के लिए ध्यान देने योग्य समय लगता है। आदर्श रूप में, मैं पृष्ठभूमि में दोनों करता हूं, लेकिन कुछ अस्पष्टता है कि पृष्ठभूमि में मुझे किस प्रकार के यूआई अपडेट करना चाहिए (मुख्य धागे के बाहर)। एक ठोस उदाहरण जो पृष्ठभूमि में डेटा पुनर्प्राप्ति और डेटा बाइंडिंग दिखाता है, बहुत उपयोगी होगा।"भारी" डेटा से निपटने के दौरान WinForms UI प्रतिक्रिया
उत्तर
पुनर्प्राप्ति, और, जा बंद एक पृष्ठभूमि धागा करने के लिए धक्का दिया जाना चाहिए कर सकते हैं - लेकिन कुछ पैटर्न यह सब जगह में डाल करने के लिए है।
असल में आप डेटा पुनर्प्राप्त करने के लिए पृष्ठभूमि थ्रेड शुरू करेंगे, एक बार ऐसा करने के बाद इसे वास्तविक यूआई अपडेट करने के लिए यूआई थ्रेड में वापस विलय करने की आवश्यकता होगी (थ्रेड में यूआई अपडेट खराब खराब हैं)।
वहाँ पृष्ठभूमि के तीन बुनियादी तरीके सूत्रण आप पता लगाने के लिए
- सबसे आसान/सबसे सीमित (और विचित्र IMO) BackgroundWorker घटक
- प्रतिनिधियों और उनके BeginInvoke()/EndInvoke() तरीकों का उपयोग कर है आसानी और लचीलापन का एक अच्छा संतुलन प्रदान करते हैं (और ThreadPool धागे का उपयोग करें) कच्चे थ्रेड वस्तुओं सबसे नियंत्रण प्रदान करता है का उपयोग कर
- , लेकिन ThreadPool धागे से सेटअप करने के लिए धीमी गति से कर रहे हैं
व्यक्तिगत रूप से मैं प्रतिनिधि विकल्प की तरफ झुकता हूं; एक बार जब आप पैटर्न प्राप्त कर लेंगे तो वे काम करने में बहुत आसान हैं। बैकग्राउंडवर्कर अच्छा लगता है लेकिन कुछ गॉथस और लापता नलसाजी है जो आपको अपेक्षा करने के लिए काम करने के लिए और अधिक बोझिल बनाती है। मुझे प्रतिनिधि दृष्टिकोण का एक संक्षिप्त नमूना चाबुक करने दो; मैं शीघ्र ही अपडेट कर देंगे ...
संपादित
यहाँ कुछ कोड है, यह VB में है, लेकिन बहुत आसान अनुलेखन यदि आप एक सी # पुरुष कर रहे हैं होना चाहिए। आपके पास बैकग्राउंड थ्रेड का व्यवहार करने के तरीके के बारे में कुछ और विकल्प हैं, इसलिए यहां दो नमूने हैं। गैर-अवरोधन मेरा पसंदीदा है, लेकिन यदि आप इसे मौजूदा कोड में फ़िट कर रहे हैं तो अवरोध आपके लिए आसान हो सकता है।
गैर अवरुद्ध, कॉलबैक विधि (GetData_Complete) यूआई धागे पर बुलाया जाएगा एक बार पृष्ठभूमि धागा पूरा
Sub Main()
Console.WriteLine("On the main thread")
Dim dataDelegate As New GetDataCaller(AddressOf GetData)
Dim iar As IAsyncResult
' Non-blocking approach using a callback method
iar = dataDelegate.BeginInvoke(AddressOf GetData_Complete, Nothing)
End Sub
Private Delegate Sub GetData_CompleteCaller(ByVal iar As IAsyncResult)
Private Sub GetData_Complete(ByVal iar As IAsyncResult)
If InvokeRequired Then
Dim invokeDelegate As New GetData_CompleteCaller(AddressOf GetData_Complete)
Invoke(invokeDelegate, New Object() {iar})
Exit Sub
End If
' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)
Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
Console.WriteLine("On the background thread!")
For index As Integer = 0 To 2
Console.WriteLine("Background thread is working")
Next
Return "Yay, background thread got the data!"
End Function
को अवरुद्ध करने उप मुख्य()
Console.WriteLine("On the main thread")
Dim dataDelegate As New GetDataCaller(AddressOf GetData)
Dim iar As IAsyncResult
' blocking approach; WaitOne() will block this thread from proceeding until the background thread is finished
iar = dataDelegate.BeginInvoke(Nothing, Nothing)
iar.AsyncWaitHandle.WaitOne()
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Sub GetData_Complete(ByVal iar As IAsyncResult)
' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)
Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
Dim result As String = dataDelegate.EndInvoke(iar)
Console.WriteLine("On the main thread again, background result is: " + result)
End Sub
Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
Console.WriteLine("On the background thread!")
For index As Integer = 0 To 2
Console.WriteLine("Background thread is working")
Next
Return "Yay, background thread got the data!"
End Function
किसी भी पृष्ठभूमि थ्रेड से UI को कभी भी अपडेट न करें, एक बार जब आप अपने सर्वर से अपना डेटा प्राप्त कर लेते हैं तो यूआई थ्रेड पर वापस आने के लिए यूआई नियंत्रण या डेटासेट को अपडेट करने के लिए जो आपका यूआई बाध्य है।
पृष्ठभूमिवर्कर का उपयोग करने से इस मामले में केवल घटनाओं को तारित करने में मदद मिलेगी।
HTH
फिल '
लोड हो रहा है (जैसा कि "डेटा स्रोत से पुनर्प्राप्त" में) छोटा हो सकता है, भले ही आप प्रतिनिधियों, पृष्ठभूमि कार्यकर्ताओं या किसी अन्य प्रोटोकॉल का उपयोग करें।लेकिन बाध्यकारी मुश्किल लगता है, क्योंकि इसमें अधिक नियंत्रण नहीं होता है, कम से कम अधिकांश डेटा-बाध्य नियंत्रणों में - आप डेटा को असीमित रूप से पुनर्प्राप्त कर सकते हैं, लेकिन एक बार जब आप पृष्ठभूमि में एक बड़े ग्रिड को इसे कैसे खिला सकते हैं? क्या यह आपका सवाल है? यदि ऐसा है, तो मुझे लगता है कि आप या तो हो सकते हैं:
- अपने दृश्य नियंत्रण को बनाएं (या सबक्लास) बनाएं, जो असीमित लोड के लिए इंटरफेस प्रदान करता है;
- एक पेज किए गए दृश्य को कार्यान्वित करें, जिसमें एक समय में केवल एन रिकॉर्ड दिखाए जाएंगे, ताकि रिकॉर्ड्स लाने/स्वरूपण करते समय यूआई अवरुद्ध न हो।
यह मेरी प्राथमिक चिंता थी। मुझे पूरा यकीन था कि मुझे नियंत्रण जैसी चीजें नहीं करनी चाहिए। डेटासोर्स = myData; पृष्ठभूमि में, लेकिन इसे पूरा करने में कुछ समय लगता है। इसलिए मैं उस काम की सीमा के बारे में अधिक उत्सुक था जिसे मैं पृष्ठभूमि में डाल सकता था। – ramnik