2011-08-04 13 views
5

मैं एक सी # ऑपरेशन विकसित कर रहा हूं और मैं एक मोडल प्रगति संवाद दिखाना चाहता हूं, लेकिन केवल जब एक ऑपरेशन लंबा होगा (उदाहरण के लिए, 3 सेकंड से अधिक)। मैं पृष्ठभूमि संचालन में अपने परिचालन निष्पादित करता हूं।केवल पृष्ठभूमि प्रगति होने पर प्रगति दिखाएं

समस्या यह है कि मुझे पहले से पता नहीं है कि ऑपरेशन लंबा या छोटा होगा या नहीं।

कुछ सॉफ्टवेयर IntelliJ के रूप में एक टाइमर aproach है। यदि ऑपरेशन एक्स समय से अधिक लेता है, तो उसके बाद एक संवाद दिखाएं।

आपको क्या लगता है कि यह लागू करने के लिए एक अच्छा पैटर्न है?

  • यूआई थ्रेड को टाइमर के साथ प्रतीक्षा करें, और वहां संवाद दिखाएं?
  • जब मैं संवाद दिखाता हूं तो मुझे DoEvents() अवश्य होना चाहिए?
+2

आप हमेशा प्रगति क्यों नहीं दिखाते हैं। यदि यह एक छोटा सा कार्य है तो प्रगति पट्टी भर जाती है और केवल थोड़ी सी मात्रा प्रदर्शित करती है। उदाहरण के लिए कार्यालय हमेशा छोटे दस्तावेज़ पर भी नीचे लोडिंग प्रगति पट्टी दिखाता है। –

+3

ऑपरेशन तेज होने पर एक झटकेदार संवाद (मिलीसेकंड) को देखना परेशान है। –

उत्तर

4

मैं कुछ संशोधनों के साथ यहां पहली पसंद के साथ जाना होगा:

पहले अलग सूत्र में संभव लंबी चलने वाली ऑपरेशन चलाते हैं।
फिर समाप्त करने के लिए प्रतीक्षा करने के लिए टाइमआउट के साथ प्रतीक्षा हैंडल द्वारा पहली स्थिति को जांचने के लिए एक अलग थ्रेड चलाएं। यदि समय बाहर ट्रिगर्स प्रगति पट्टी दिखाते हैं।

कुछ की तरह:

private ManualResetEvent _finishLoadingNotifier = new ManualResetEvent(false); 

private const int ShowProgressTimeOut = 1000 * 3;//3 seconds 


private void YourLongOperation() 
{ 
    .... 

    _finishLoadingNotifier.Set();//after finish your work 
} 

private void StartProgressIfNeededThread() 
{ 
    int result = WaitHandle.WaitAny(new WaitHandle[] { _finishLoadingNotifier }, ShowProgressTimeOut); 

    if (result > 1) 
    { 
     //show the progress bar. 
    } 
} 
4

यहाँ मैं करना चाहते हैं क्या करना है:

1) एक BackgroundWorker का उपयोग करें।

2) इससे पहले कि आप RunWorkerAsync विधि को कॉल करें, वर्तमान समय को एक चर में संग्रहीत करें।

3) DoWork ईवेंट में, आपको ReportProgress को कॉल करने की आवश्यकता होगी। प्रोग्रेस चेंजेड इवेंट में, यह देखने के लिए जांचें कि क्या समय तीन सेकंड से अधिक हो गया है या नहीं। यदि ऐसा है, तो संवाद दिखाएं। http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

नोट::

यहाँ BackgroundWorker के लिए एक MSDN उदाहरण है सामान्य तौर पर, मैं Ramhound की टिप्पणी से सहमत हैं। बस प्रगति प्रदर्शित करें। लेकिन अगर आप BackgroundWorker का उपयोग नहीं कर रहे हैं, तो मैं इसका उपयोग करना शुरू कर दूंगा। यह आपके जीवन को आसान बना देगा।

0

मैं अपने यूआई तर्क को शेष एप्लिकेशन से अलग करने के लिए, पृष्ठभूमि गतिविधि से प्रगति संवाद को अलग रखूंगा। तो अनुक्रम होगा (यह अनिवार्य रूप से क्या इंटेलीजे करता है के समान है):

  1. यूआई पृष्ठभूमि आपरेशन (एक BackgroundWorker में) शुरू होता है और एक्स सेकंड के लिए एक टाइमर की स्थापना
  2. टाइमर यूआई शो समाप्त हो रहा है जब प्रगति संवाद (यदि पृष्ठभूमि कार्य अभी भी चल रहा है)
  3. जब पृष्ठभूमि कार्य को पूरा करता टाइमर रद्द कर दिया गया और संवाद (यदि हो तो)

बंद कर दिया है एक टाइमर के बजाय एक अलग थ्रेड अधिक संसाधन है का उपयोग करना कुशल।

2

आप यह मानते हुए एक DoPossiblyLongOperation(), ShowProgressDialog() और HideProgressDialog() तरीकों है, तो आप आप के लिए भारी उठाने करने के लिए TPL इस्तेमाल कर सकते हैं:

var longOperation = new Task(DoPossiblyLongOperation).ContinueWith(() => myProgressDialog.Invoke(new Action(HideProgressDialog))); 

if (Task.WaitAny(longOperation, new Task(() => Thread.Sleep(3000))) == 1) 
    ShowProgressDialog(); 
+0

थ्रेड की बजाय। सो जाओ, मैं टास्क का सुझाव दूंगा। डेले, ताकि पूरे धागे को सोने के लिए न रखा जाए (एक ही थ्रेड पर कई कार्य चल रहे हों)। – MCattle

+1

@ एमएमएटल: सच। इस उत्तर को लिखने के समय, कार्य। फ्रेमवर्क ढांचे में मौजूद नहीं था, और एक सिस्टम का उपयोग कर रहा था। थ्रेडिंग। टिमर सरल सिद्धांत को प्रदर्शित करने के लिए चीजों को बहुत जटिल बना देगा जो मैं दिखाने की कोशिश कर रहा था। –

0

सिफारिश की गैर-अवरुद्ध समाधान है और कोई नया सूत्र:

try 
{ 
    var t = DoLongProcessAsync(); 
    if (await Task.WhenAny(t, Task.Delay(1000)) != t) ShowProgress(); 
    await t; 
} 
finally 
{ 
    HideProgress(); 
} 
संबंधित मुद्दे