2010-08-02 11 views
8

अपडेट नहीं कर रहा है मेरे पास एक प्रोग्रेसबारविंडो है जिसमें एक प्रगति पट्टी है और उस पर एक रद्द बटन है जिसका उपयोग मैं फ़ाइल I/O पर प्रगति की रिपोर्ट करने के लिए करता हूं। हालांकि, प्रोग्रेसबारविंडो का UI थ्रेड और मेरी मुख्य विंडो दोनों पृष्ठभूमि कार्यकर्ता में किए जा रहे सभी कार्यों के बावजूद लटका है। प्रगति पट्टी प्रदान की जाती है, जैसा कि मेरी मुख्य खिड़की है, लेकिन बैकग्राउंडर अपनी बात करता है, लेकिन अद्यतन नहीं करता है। निम्नलिखित कोड मुख्य विंडो के निर्माता के अंत में कहा जाता है:सी # प्रोग्रेसबार

iCountLogLinesProgressBar = new ProgressBarWindow(); 
iCountLogLinesProgressBar.cancelButton.Click += EventCountLogLinesProgressBarCancelButtonClicked; 
iCountLogLinesProgressBar.Show(); 

iCountLogRecords = new BackgroundWorker(); 
iCountLogRecords.DoWork += EventCountLogLinesDoWork; 
iCountLogRecords.ProgressChanged += EventCountLogLinesProgressChanged; 
iCountLogRecords.RunWorkerCompleted += EventCountLogLinesRunWorkerCompleted; 
iCountLogRecords.WorkerReportsProgress = true; 
iCountLogRecords.WorkerSupportsCancellation = true; 
iCountLogRecords.RunWorkerAsync(new BinaryReader(File.Open(iMainLogFilename, FileMode.Open, FileAccess.Read))); 

EventCountLogLinesProgressChanged() इस तरह दिखता है:

private void EventCountLogLinesProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    iCountLogLinesProgressBar.Value = e.ProgressPercentage; 
} 

यहाँ ProgressBarWindow का एक छोटा संस्करण है (बाकी है सिर्फ एक setters की जोड़ी):

public partial class ProgressBarWindow : Window 
{ 
    public ProgressBarWindow() 
    { 
     InitializeComponent(); 
     this.progressBar.Value = this.progressBar.Minimum = 0; 
     this.progressBar.Maximum = 100; 
    } 

    public double Value 
    { 
     get 
     { 
      return progressBar.Value; 
     } 
     set 
     { 
      this.progressBar.Value = value; 
     } 
    } 
} 

मैं एक dispatcher.invoke प्रतिनिधि में मूल्य सेटर लाइन लपेटकर की कोशिश की है लेकिन यह है कि मुझे एक Stac देता है k ओवरफ़्लो (मुझे पृष्ठभूमि के रूप में एक dispatcher.invoke लाइन नहीं होनी चाहिए, जैसा कि पृष्ठभूमि कार्यकर्ता यूआई थ्रेड में प्रगति की प्रगति करता है, है ना?)। मैंने msdn और googled की जांच की है लेकिन मुझे इस समस्या के साथ किसी और को नहीं मिल रहा है।

संपादित क्षमा याचना, मैं अपने सरलीकृत कोड यूआई धागा अवरुद्ध एहसास नहीं था, मैं बिल्कुल वैसा ही व्यवहार मिलता है एक BackgroundWorker उपयोग करने के बावजूद इसलिए मैं ग़लती से मान लिया है कि वे बराबर थे। मुझे यह उल्लेख करना चाहिए था कि मैं बैकग्राउंडवर्कर का उपयोग कर रहा था: पी

उत्तर

14

आप यूआई थ्रेड को अवरुद्ध कर रहे हैं, इसलिए यह आपके लूप समाप्त होने तक यूआई को फिर से प्रस्तुत नहीं करेगा।

पृष्ठभूमि प्रसंस्करण को एक अलग थ्रेड में ले जाएं, और उपयुक्त Dispatcher कॉल (या BackgroundWorker) का उपयोग मार्शल यूआई अपडेट को यूआई थ्रेड पर वापस कॉल करने के लिए करें।

यदि आपकी प्रगति पट्टी वास्तव में बस एक टाइमर होने का मतलब है, तो आप इसे अपडेट करने के लिए Timer कक्षाओं में से एक का उपयोग कर सकते हैं।

संपादित करें: ठीक है, अब आपने कोड बदल दिया है, यह मेरे लिए ठीक दिखता है। यह थ्रेड-सुरक्षित होना चाहिए क्योंकि आप यूआई थ्रेड पर केवल यूआई बदल रहे हैं। क्या आपका पृष्ठभूमि कार्यकर्ता निश्चित रूप से समय-समय पर प्रगति की रिपोर्ट कर रहा है?

+0

मेरे पास ऊपर एक पृष्ठभूमि कार्यकर्ता है, लेकिन क्या मुझे अपने मूल्य सेटटर के लिए dispatcher.invoke कॉल की भी आवश्यकता है? – CalumMcCall

+0

@ teflon19: नहीं, आपको कुछ और करने की आवश्यकता नहीं है - यह सुनिश्चित करने के अलावा कि आप पृष्ठभूमि कार्यकर्ता में प्रगति की रिपोर्ट कर रहे हैं। –

+0

प्रगति में परिवर्तन होने पर ही मैं प्रगति की रिपोर्ट कर रहा हूं, बहुत से प्रगतिशील घटनाएं चीजों को धीमा कर रही थीं, लेकिन यूआई अभी भी स्थिर हो गई है। क्या कोई कारण है कि प्रोग्रेसबार यूआई थ्रेड पृष्ठभूमिवर्कर से प्रभावित होगा? – CalumMcCall

3

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

+2

-1: कॉलिंग एप्लिकेशन। डॉवेट्स सीधे खराब अभ्यास है।यह UI थ्रेड को अपने संदेश पंपिंग प्रक्रिया को दोबारा दर्ज करने का कारण बनता है जो कुछ ग़लत समस्याओं का कारण बन सकता है। अपने आवेदन को सही ढंग से लिखना बेहतर है और यूआई थ्रेड को सामान्य रूप से संदेशों के लिए पंप करने की अनुमति देता है। –

+2

यह पैमाने पर निर्भर करता है। यदि यह एक छोटा डेस्कटॉप ऐप है जो उदाहरण के लिए एक साधारण अपडेट करता है, तो आप इसे एक थ्रेड में एप्लिकेशन.डिवेन्ट्स() के साथ लिखने में 15 मिनट व्यतीत कर सकते हैं, या इसे जटिल बना सकते हैं, विधि आवेषण में सरल विधि कॉल बदल सकते हैं। मैंने अभी एक और विकल्प समझाया है, यह निर्दिष्ट करते हुए कि ज्यादातर मामलों में जॉन स्कीट का विकल्प बेहतर है। इसलिए मुझे एक विकल्प की गणना करने के लिए नीचे वोट मिला। अच्छा लगा। – AlexanderMP

+0

यह मेरी राय है कि इसके वर्तमान रूप में आपका उत्तर डेवलपर्स को यूआई अपडेट की समस्याओं (जितने लोग करते हैं) के लिए एक चांदी बुलेट के रूप में एप्लिकेशन का उपयोग करके बुरी आदतों को विकसित करने के लिए सवाल पढ़ सकता है। प्रश्न में उद्देश्य के लिए मैं बस * कभी भी एप्लिकेशन का उपयोग नहीं करता हूं। हां, जॉन स्कीट को सुनना इस उदाहरण में अच्छी सलाह है, और आपने अभी एक और विकल्प बताया है, लेकिन मेरी राय में यह एक बुरा विकल्प है। लेकिन यह सिर्फ एक व्यक्ति की राय है, जो आपके उत्तर के स्कोर में दिखाई देता है। –

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