wpf
थ्रेड एफिनिटी एक्सेसिंग यूआई एलिमेंट्स
खोज…
एक कार्य के भीतर से UI तत्व तक पहुँचना
सभी UI तत्व एक प्रोग्राम के मुख्य थ्रेड में निर्मित और निवास करते हैं। किसी अन्य थ्रेड से इन तक पहुँच .net फ्रेमवर्क रनटाइम द्वारा निषिद्ध है। मूल रूप से ऐसा इसलिए है क्योंकि सभी UI तत्व थ्रेड सेंसिटिव संसाधन होते हैं और बहु-थ्रेडेड वातावरण में किसी संसाधन तक पहुँचने के लिए थ्रेड-सुरक्षित होना आवश्यक है। यदि यह क्रॉस थ्रेड ऑब्जेक्ट एक्सेस की अनुमति देता है, तो स्थिरता पहले स्थान पर प्रभावित होगी।
इस परिदृश्य पर विचार करें:
हमारे पास किसी कार्य के अंदर होने वाली गणना है। मुख्य धागे की तुलना में दूसरे धागे में कार्य चलाया जाता है। जबकि गणना आगे बढ़ती है, हमें एक प्रगति पट्टी को अपडेट करने की आवश्यकता होती है। यह करने के लिए:
//Prepare the action
Action taskAction = new Action( () => {
int progress = 0;
Action invokeAction = new Action( () => { progressBar.Value = progress; });
while (progress <= 100) {
progress = CalculateSomething();
progressBar.Dispatcher.Invoke( invokeAction );
}
} );
//After .net 4.5
Task.Run( taskAction );
//Before .net 4.5
Task.Factory.StartNew( taskAction ,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
हर UI एलिमेंट में एक डिस्पैचर ऑब्जेक्ट होता है जो उसके DispatcherObject
आंसर ( System.Windows.Threading
namespace के अंदर) से आता है। डिस्पैचर निर्दिष्ट प्रतिनिधि को उस थ्रेड पर निर्दिष्ट प्राथमिकता पर तुल्यकालिक रूप से निष्पादित करता है जिस पर डिस्पैचर जुड़ा हुआ है। चूंकि निष्पादन को समन्वित किया जाता है, कॉलर कार्य को इसके परिणाम की प्रतीक्षा करनी चाहिए। इससे हमें प्रेषणकर्ता के प्रतिनिधि के अंदर भी int progress
का उपयोग करने का अवसर मिलता है।
हम यूआई तत्व को अतुल्यकालिक रूप से अपडेट करना चाहते हैं, फिर invokeAction
परिभाषा में परिवर्तन कर सकते हैं:
//Prepare the action
Action taskAction = new Action( () => {
int progress = 0;
Action<int> invokeAction = new Action<int>( (i) => { progressBar.Value = i; } )
while (progress <= 100) {
progress = CalculateSomething();
progressBar.Dispatcher.BeginInvoke(
invokeAction,
progress );
}
} );
//After .net 4.5
Task.Run( taskAction );
//Before .net 4.5
Task.Factory.StartNew( taskAction ,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
इस बार हमने int progress
पैक किया और प्रतिनिधि के लिए एक पैरामीटर के रूप में उपयोग किया।