2009-11-08 21 views
5

पर एक मोडल संवाद चलाएं मैं मानक सर्वर का उपयोग कर एक सरल डेटा यूआई लिख रहा हूं। SQL सर्वर से टाइप किए गए डेटासेट को डेटाबेस डेटाबेस।एक गैर-यूआई थ्रेड

मेरे पास एक पुनः लोड बटन है जो डाटाबेस से नया डेटा प्राप्त करने के लिए सभी डेटाएडाप्टर पर Fill पर कॉल करता है (यदि किसी अन्य उपयोगकर्ता ने डेटा बदल दिया है)।

इसमें कुछ समय लगता है, जिसके दौरान यूआई जमे हुए है। इसे यूआई थ्रेड पर चलाया जाना चाहिए या डाटाबेसिंग इवेंट हैंडलर क्रॉस-थ्रेड अपवाद फेंकना चाहिए।

मैं यूआई थ्रेड डेटाबेस से कनेक्ट होने पर पृष्ठभूमि थ्रेड पर एक मोडल "कृपया प्रतीक्षा करें" संवाद दिखाना चाहता हूं (ताकि इसे एनिमेटेड किया जा सके)।

मैं गैर-यूआई थ्रेड पर एक मॉडल संवाद बॉक्स कैसे दिखा सकता हूं?


संपादित करें: मुझे पता है कि सबसे अच्छा अभ्यास पृष्ठभूमि में ऑपरेशन चलाने के लिए है, लेकिन मैं ऐसा नहीं कर सकते क्योंकि डेटा बाइंडिंग की घटनाओं की है कि।

उत्तर

8

आपको इसके विपरीत करना चाहिए। पृष्ठभूमि थ्रेड पर अपनी लंबी चल रही प्रक्रिया चलाएं और यूआई थ्रेड को उपयोगकर्ता क्रियाओं के जवाब देने के लिए मुक्त छोड़ दें।

यदि आप प्रसंस्करण करते समय किसी भी उपयोगकर्ता क्रिया को अवरुद्ध करना चाहते हैं तो आपके पास मोडल संवाद सहित कई विकल्प हैं। एक बार जब पृष्ठभूमि धागा प्रसंस्करण पूरा करता है आप परिणाम

+0

जैसा कि मैंने इस प्रश्न में बताया है, मैं नहीं कर सकता। मुझे अच्छी तरह से पता है कि यह सबसे अच्छा अभ्यास है। – SLaks

+0

मुझे लगता है कि आप अभी भी कर सकते हैं। इसका मतलब यह है कि पृष्ठभूमि धागे को सीधे डेटा अपडेट नहीं करना चाहिए। उन्हें पुनर्प्राप्त करें, उन्हें पैकेज करें और UI – mfeingold

+0

को अपडेट करने के लिए मुख्य थ्रेड पर प्रतिनिधि दें, मैं आपकी दुविधा को समझता हूं, लेकिन मुझे अभी भी लगता है कि मैं जो सुझाव दे रहा हूं वह वैकल्पिक – mfeingold

0
using(var frmDialog = new MyPleasWaitDialog()) { 
    // data loading is started after the form is shown 
    frmDialog.Load += (_sender, _e) { 
     // load data in separate thread 
     ThreadPool.QueueWorkItem((_state)=> { 
      myAdapter.Fill(myDataSet); 
      // refresh UI components in correct (UI) thread 
      frmDialog.Invoke((Action)myDataControl.Refresh); 
      // close dialog 
      frmDialog.Invoke((Action)frmDialog.Close()); 
     } 
    } 

    // shows dialog 
    frmDialog.ShowDialog(this); 
} 
+0

आपको अलग-अलग डेटासेट में लोड डेटा की आवश्यकता है, जो डेटाग्रिड से बाध्य नहीं है, और उसके बाद डेटाग्रिड को नए डेटासेट में पुनर्निर्मित करें। और/या डेटासेट/डेटाटेबल पर "BeginLoadData()" और "EndLoadData" का उपयोग करने का प्रयास करें। – TcKs

+1

जैसा कि मैंने प्रश्न में व्याख्या करने की कोशिश की, 'myAdapter.Fill' पृष्ठभूमि थ्रेड पर कॉल किए जाने पर ग्रिड के डाटाबेसिंग ईवेंट हैंडलर में एक अवैधऑपरेशन अपवाद फेंकता है। तालिका पर 'BeginLoadData' को कॉल करने से मदद नहीं मिलती है। – SLaks

+1

तो, आपको एक और डेटासेट भरना होगा और फिर डेटाग्रिड को "नया" (भरवां) डेटासेट उदाहरण में दोबारा जोड़ना होगा। – TcKs

2

कोड databinding घटनाओं यूआई से decoupled किया जाना है, शायद आंकड़ा अंतरण वस्तु के कुछ प्रकार का उपयोग कर की जरूरत है चलाने के बारे में मुख्य थ्रेड सूचित कर सकते हैं।

फिर आप क्वेरी ऑपरेशन को एक अलग थ्रेड या BackgroundWorker में चला सकते हैं, और UI थ्रेड को छोड़ दें।

संपादित करें: वास्तव में त्वरित इसे ठीक करने के रास्ते InvokeRequired और .Invoke का उपयोग कर अपने स्वयं के प्रतिनिधि में चलाने के लिए घटनाओं प्राप्त करने के लिए है। यह यूआई संदर्भ विधियों देगा। मेरा सहकर्मी ऐसा करता है जैसे यह शैली से बाहर जा रहा है और इससे मुझे कोई अंत नहीं होता क्योंकि यह शायद ही कभी ऐसा करने का अच्छा विचार है ... लेकिन यदि आप एक तेज समाधान चाहते हैं तो यह काम करेगा। (मैं काम पर नहीं हूं इसलिए मेरे पास नमूना नहीं है; मैं कुछ के साथ आने की कोशिश करूंगा।)

संपादित करें 2: मुझे यकीन नहीं है कि आप जो पूछ रहे हैं वह संभव है। मैंने एक नमूना ऐप बनाया जिसने दूसरे थ्रेड में एक मोडल डायलॉग बनाया, और यह मॉडेलिस बन गया। एक मोडल संवाद का उपयोग करने के बजाय, क्या आप प्रगति परिवर्तन को इंगित करने के लिए कुछ अन्य नियंत्रण या नियंत्रण सेट का उपयोग कर सकते हैं, अधिकतर संभवतः उसी रूप पर?

+0

क्या ऐसा करने का कोई आसान तरीका है और अभी भी अद्यतन घटनाओं के साथ मानक डेटाबेस का उपयोग करना है? मैं इस परियोजना को जल्दी खत्म करने की कोशिश कर रहा हूं। – SLaks

+0

पुन। संपादित करें: मैं डेटाग्रिड के अंदर 'Invoke' कॉल नहीं डाल सकता। – SLaks

+0

पुन: संपादित करें 2: आप बहुत अच्छे हो सकते हैं। अगर यह एक साधारण सवाल था, तो मैंने इसे यहां नहीं पूछा होता। फ़ॉर्म पर नियंत्रण डालने के लिए, यह भी बदतर है - यह एक अलग थ्रेड के स्वामित्व वाले फॉर्म पर कुछ नियंत्रण रखना असंभव है। – SLaks

0

यहां डेटा के लोड हो रहा है ऐसा करने के लिए BackgroundWorker का उपयोग कर बनाने और चलाने के एक उपयोगकर्ता के अनुकूल प्रपत्र दिखाने के लिए 'रिकॉर्ड लोड हो रहा है' का एक उदाहरण या इसी तरह की है ...

public void Run() 
    { 
     bgWorkrFillDS = new BackgroundWorker(); 
     bgWorkrFillDS.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkrFillDS_RunWorkerCompleted); 
     bgWorkrFillDS.DoWork += new DoWorkEventHandler(bgWorkrFillDS_DoWork); 
     bgWorkrFillDS.RunWorkerAsync(); 
    } 

    void bgWorkrFillDS_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker bgWrkrFillDS = (BackgroundWorker)sender as BackgroundWorker; 
     if (bgWrkrFillDS != null) 
     { 
      // Load up the form that shows a 'Loading....' 
      // Here we fill in the DS 
      // someDataSetAdapter.Fill(myDataSet); 
     } 
    } 


    void bgWorkrFillDS_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // Hide or unload the form when the work is done 
    } 

आशा इस मदद करता है ... ख्याल रखना , टॉम।

+1

कृपया प्रश्न पढ़ें। पृष्ठभूमि थ्रेड पर 'someDataSetAdapter.Fill' को कॉल करना एक अवैधऑपरेशन अपवाद फेंक देगा। – SLaks

0

मैंने पृष्ठभूमि में लोड होने, एक नई डेटासेट बनाकर, इस समस्या को हल किया, फिर UI थ्रेड पर DataSet.Merge पर कॉल किया। आपकी सलाह के लिए सभी को धन्यवाद, जिसने इस समाधान को जन्म दिया।

एक अतिरिक्त बोनस के रूप में, यह अधिक चलाता है जितना तेज़ होता है (पृष्ठभूमि में Fill पर कॉल करता है, जो केवल ग्रिड के साथ काम करता है)। क्या किसी को पता है क्यों?

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