c# - Is BackgroundWorker the only way to keep a WCF/WPF application responsive? -


सी #, डब्ल्यूसीएफ, डब्ल्यूपीएफ का उपयोग कर क्लाइंट / सर्वर डेस्कटॉप एप। चूंकि हर एक्शन को सर्वर (यात्रा / बनाने / सहेज / हटाएं / आदि) की यात्रा की आवश्यकता होती है, इसलिए हर एक्शन में पूरे यूज़ को फ्रीज करने की क्षमता होती है। service.GetAll () को कॉल के साथ एक सरल कार्यान्वयन का एक उदाहरण है जो "लंबे समय" (कुछ सौ मिलीसेकंड से अधिक) ले सकता है:

  निजी शून्य btnRefresh_Click (ऑब्जेक्ट प्रेषक, RoutedEventArgs ई) {vm.Users.Clear (); फोरछा (सेवा में विभिन्न उपयोगकर्ता। गेटअलेउजर्स ()) vm.Users.Add (उपयोगकर्ता); }   

(एक तरफ: मुझे यह जानना अच्छा लगेगा कि क्यों है AddRange है और नहीं।)

BackgroundWorker बचाव के लिए: <पूर्व> निजी शून्य btnRefresh_Click (ऑब्जेक्ट प्रेषक, RoutedEventArgs ई) {var कार्यकर्ता = नया पृष्ठभूमिवर्कर (); Worker.DoWork + = (s, e) = & gt; {Dispatcher.BeginInvoke (एक्शन) प्रतिनिधि () {btnRefresh.IsEnabled = false;}); E.Result = service.GetAllUsers (); }; Worker.RunWorkerCompleted + = (s, e) = & gt; {Vm.Users.Clear (); विदेशी भाषा (विभिन्न प्रयोक्ता में (सूची & amp; lt; UserDto & gt;) ई। परिणाम) vm.Users.Add (उपयोगकर्ता); Dispatcher.BeginInvoke ((कार्रवाई) प्रतिनिधि () {btnRefresh.IsEnabled = true;}); }; worker.RunWorkerAsync (); }

(एक तरफ: कोड ऊपर सरलीकृत किया गया है, लेकिन यह इसका सार है।)

कोड का उपयोग करके BackgroundWorker बिल्कुल काम करता है मुझे यह करना चाहिए ऐप हर समय उत्तरदायी रहता है, और कॉल को कॉल की अवधि के लिए अक्षम कर दिया गया है। हालांकि, इसका मतलब है कि उपयोगकर्ता हर संभव कार्रवाई करने के लिए 15 लाइन जोड़ना चाहता है।

ऐसा कहें ऐसा नहीं है।

नहीं, पृष्ठभूमिवर्ककार एकमात्र तरीका नहीं है, लेकिन यह एक ही तरीका है। किसी भी अन्य तरीके से सभी को एसिंक्रोनस के रूप में शामिल किया जाएगा जिसमें UI को अपडेट करने के लिए Dispatch.BeginInvoke का उपयोग करने की आवश्यकता होती है। उदाहरण के लिए आप थ्रेडपूल का उपयोग कर सकते हैं:

  थ्रेडपूल.क्यूयूयूयूएडरवकर्इटम (राज्य = & gt; {Dispatcher.BeginInvoke (एक्शन) प्रतिनिधि () {btnRefresh.IsEnabled = false ;}); Foreach (सेवा में उपयोगकर्ता। गेटअलेउज़र्स ()) vm.Users.Add (उपयोगकर्ता); Dispatcher.BeginInvoke ((कार्रवाई) प्रतिनिधि) () {btnRefresh.IsEnabled = true;});});   

यदि यह एक आवर्ती पैटर्न है (एक बटन कुछ एक्शन को ट्रिगर करेगा जिसे एसिंक्रोनस तरीके से क्रियान्वित किया जाना चाहिए, इस प्रक्रिया के दौरान बटन को अक्षम किया जा रहा है) आप इसे एक विधि में लपेट कर सकते हैं:

  निजी शून्य निष्पादित करना (क्रिया कार्रवाई, नियंत्रण ट्रिगरिंग नियंत्रण) {ThreadPool.QueueUserWorkItem (राज्य = & gt; {Dispatcher.BeginInvoke ((कार्रवाई) प्रतिनिधि) () triggeringControl.IsEnabled = false;}); कार्रवाई () ; डिस्पैचर। बेनिइन इन्वोक (एक्शन) प्रतिनिधि () {ट्रिगरिंग कंट्रोल.आईएसएएनएबल = सच;});}); }   

... और इसे कॉल करें:

  PerformAsync ((=) = & gt; {foreach (सेवा में उपयोगकर्ता उपयोगकर्ता। GETAllUsers ()) vm। उपयोगकर्ता। जोड़ें (उपयोगकर्ता);}, बीटीएन रीफेश);   

ThreadPool का उपयोग करने के विकल्प के रूप में, आपको शायद यह भी देखना चाहिए।

ऐसा करते समय आपको ध्यान देना चाहिए कि कैसे आप यूआई स्थिति को संभालते हैं उदाहरण के लिए आपके पास एक से अधिक नियंत्रण होते हैं जो एक ही कार्रवाई को चालू करता है, सुनिश्चित करें कि कार्रवाई के दौरान उन सभी को अक्षम कर दिया गया है।

नोट: ये सिर्फ त्वरित विचार हैं कोड का परीक्षण नहीं किया गया है, इसमें त्रुटियां हो सकती हैं समाप्त समाधानों से अधिक चर्चा सामग्री के रूप में माना जाना अधिक है

Comments