कॉम्पैक्ट फ्रेमवर्क/थ्रेडिंग - विकल्प के बाद संदेश नियंत्रण अन्य नियंत्रणों पर प्रदर्शित होता है

मैं एक ऐसे ऐप पर काम कर रहा हूं जो बाहरी सर्वर से अद्यतनों का एक समूह पकड़ लेता है और स्थापित करता है, और थ्रेडिंग के साथ कुछ मदद की ज़रूरत है। उपयोगकर्ता इस प्रक्रिया का पालन करता है:

  • क्लिक बटन
  • अपडेट के लिए विधि जांचता है, गणना वापस आती है।
  • यदि 0 से अधिक है, तो उपयोगकर्ता से पूछें कि क्या वे MessageBox.Show() का उपयोग करके इंस्टॉल करना चाहते हैं।
  • यदि हां, तो यह लूप के माध्यम से चलता है और पृष्ठभूमि में इसे चलाने के लिए प्रत्येक अद्यतन के रन() विधि पर BeginInvoke() को कॉल करता है।
  • मेरी अपडेट क्लास में कुछ ईवेंट हैं जिनका उपयोग प्रगति पट्टी आदि को अपडेट करने के लिए किया जाता है।

प्रोग्रेस बार अपडेट ठीक हैं, लेकिन संदेशबॉक्स को स्क्रीन से पूरी तरह से साफ़ नहीं किया गया है क्योंकि उपयोगकर्ता हां क्लिक करने के बाद अपडेट लूप ठीक से शुरू होता है (नीचे स्क्रीनशॉट देखें)।

  • अपडेट लूप शुरू होने से पहले संदेशबॉक्स को तुरंत गायब करने के लिए मुझे क्या करना चाहिए?
  • क्या मुझे BeginInvoke() के बजाय थ्रेड का उपयोग करना चाहिए?
  • क्या मुझे एक अलग धागे पर प्रारंभिक अद्यतन जांच करनी चाहिए और उस थ्रेड से MessageBox.Show() को कॉल करना चाहिए?

संहिता

// Button clicked event handler code...
DialogResult dlgRes = MessageBox.Show(
    string.Format("There are {0} updates available.\n\nInstall these now?", 
    um2.Updates.Count), "Updates Available", 
    MessageBoxButtons.YesNo, 
    MessageBoxIcon.Question, 
    MessageBoxDefaultButton.Button2
);

if (dlgRes == DialogResult.Yes)
{
    ProcessAllUpdates(um2); 
}

// Processes a bunch of items in a loop
private void ProcessAllUpdates(UpdateManager2 um2)
{
    for (int i = 0; i < um2.Updates.Count; i++)
    {
        Update2 update = um2.Updates[i];

        ProcessSingleUpdate(update);

        int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count);

        UpdateOverallProgress(percentComplete);
    }
}

// Process a single update with IAsyncResult
private void ProcessSingleUpdate(Update2 update)
{
    update.Action.OnStart += Action_OnStart;
    update.Action.OnProgress += Action_OnProgress;
    update.Action.OnCompletion += Action_OnCompletion;

    //synchronous
    //update.Action.Run();

   //async
    IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); });
}

स्क्रीनशॉट

Windows Mobile Bug

0
ro fr bn

3 उत्तर

क्या आपने ए डालने की कोशिश की है

Application.DoEvents()

यहाँ पर

if (dlgRes == DialogResult.Yes)
{
   Application.DoEvents(); 
   ProcessAllUpdates(um2); 
}
0
जोड़ा

आपका यूआई अपडेट नहीं हो रहा है क्योंकि उपयोगकर्ता इंटरफ़ेस थ्रेड में सभी काम हो रहा है। आपका कॉल:

this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); }) 

कह रहा है कि "यह" (आपका फॉर्म) बनाया गया थ्रेड पर अपडेट.ऑक्शन.रुन() का आह्वान करें, जो यूजर इंटरफेस थ्रेड है।

Application.DoEvents()

वास्तव में यूआई थ्रेड को स्क्रीन को फिर से चलाने का मौका देगा, लेकिन मैं नए प्रतिनिधि को बनाने के लिए प्रेरित हूं, और उस पर BeginInvoke को कॉल करें।

यह थ्रेड पूल से आवंटित एक अलग थ्रेड पर update.Action.Run() फ़ंक्शन निष्पादित करेगा। फिर अद्यतन पूरा होने तक आप IAsyncResult की जांच कर सकते हैं, प्रत्येक चेक के बाद अपडेट ऑब्जेक्ट को इसकी प्रगति के लिए पूछताछ कर सकते हैं (क्योंकि आपके पास अन्य थ्रेड प्रगति पट्टी/यूआई अपडेट नहीं हो सकता है), फिर एप्लिकेशन को कॉल करना। DoEvents ()।

आपको एंडइनवोक() को बाद में कॉल करना होगा अन्यथा आप संसाधनों को लीक कर सकते हैं

मैं प्रगति संवाद पर रद्द बटन डालने का भी प्रयास करता हूं, और एक टाइमआउट जोड़ता हूं, अन्यथा यदि अपडेट फंस जाता है (या बहुत लंबा लगता है) तो आपका एप्लिकेशन हमेशा के लिए बंद हो जाएगा।

0
जोड़ा

@ जॉन Sibly

आप नहीं कॉलिंग से दूर हो सकते हैं WinForms से किसी भी नकारात्मक नतीजे के बिना व्यवहार करते समय EndInvoke।

नियम के लिए एकमात्र दस्तावेज अपवाद जिसे मैं जानता हूं, विंडोज फॉर्म में है, जहां आपको आधिकारिक तौर पर Control.BeginInvoke को कॉल करने के लिए अनुमति दी जाती है, जिसे कंट्रोल.इंड इनवोक कॉल करने के लिए परेशान किए बिना।

हालांकि, अन्य सभी मामलों में जब आप शुरुआती/अंत Async पैटर्न से निपटते हैं तो आपको यह मानना ​​चाहिए कि यह रिसाव होगा, जैसा आपने कहा था।

0
जोड़ा