2009-07-01 11 views
12

मेरे कार्यक्रम में [सी # + विनफॉर्म]। मेरे पास प्रगति बार & सूचीदृश्य है।विनफॉर्म प्रोग्रेस बार अपडेट नहीं करता है (सी #)

एक विधि के माध्यम से मैं कुछ संचालन कर रहा हूं & फिर सूचीदृश्य में डेटा अपडेट कर रहा हूं। रिकॉर्ड किए गए रिकॉर्ड्स का वह मूल्य वह मूल्य है जिसे मैं प्रोग्रेसबार.वल्यू प्रॉपर्टी के लिए सेट कर रहा हूं। मैं यहां क्या चाहता हूं, प्रगति पट्टी के मूल्य के अनुसार, इसे अपनी प्रगति दिखानी चाहिए। हालांकि प्रगति पट्टी अद्यतन नहीं हो रही है। केवल विधि निष्पादन के अंत में प्रगति बार पूरी प्रगति दिखाता है यानी 100%

क्या कोई इस संबंध में मेरी सहायता कर सकता है?

धन्यवाद, अमित

+2

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

उत्तर

26

ऐसा लगता है कि आप यूआई धागा अवरुद्ध कर रहे हैं - यानी आप प्रणाली किसी भी पेंटिंग करने के लिए जारी नहीं किया है।

एक हैकी जवाब Application.DoEvents() को आपके कोड में इंजेक्ट करना है - लेकिन यह जोखिम भरा है, और फिर से प्रवेश करने में समस्याएं हैं; और यह सिर्फ थोड़ा हैकी है।

एक बेहतर विकल्प एक BackgroundWorker पर प्रोसेसिंग करने के लिए समय-समय पर यूआई धागा का उपयोग करने जा बातें (Control.Invoke) अद्यतन करने के लिए हो सकता है - लेकिन यह मुश्किल हो सकता है अगर आप एक ListView करने के लिए आइटम के बहुत सारे जोड़ रहे हैं।

पूर्ण उदाहरण (आप बैच करना चाह सकते हैं, हालांकि यूआई अद्यतन - नहीं एक बार में एक पंक्ति):

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Forms; 

class MyForm : Form 
{ 
    BackgroundWorker worker; 
    ListView list; 
    Button btn; 
    ProgressBar bar; 
    public MyForm() 
    { 
     Text = "Loader"; 
     worker = new BackgroundWorker(); 
     worker.WorkerReportsProgress = true; 
     worker.ProgressChanged += worker_ProgressChanged; 
     worker.DoWork += worker_DoWork; 
     worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
     list = new ListView(); 
     list.Dock = DockStyle.Fill; 
     Controls.Add(list); 
     btn = new Button(); 
     btn.Text = "Load"; 
     btn.Dock = DockStyle.Bottom; 
     Controls.Add(btn); 
     btn.Click += btn_Click; 
     bar = new ProgressBar(); 
     bar.Dock = DockStyle.Top; 
     Controls.Add(bar); 
    } 

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     btn.Enabled = true; 
    } 

    void btn_Click(object sender, EventArgs e) 
    { 
     worker.RunWorkerAsync(); 
     btn.Enabled = false; 
    } 


    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      string newRow = "Row " + i.ToString(); 
      worker.ReportProgress(i, newRow); 
      Thread.Sleep(100); 
     } 
    } 

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     list.Items.Add((string)e.UserState); 
     bar.Value = e.ProgressPercentage; 
    } 

    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new MyForm()); 
    } 
} 
0

ProgressBar.Value होना चाहिए 0 और 100 के

के बीच मेरा अनुमान है कि आपकी समस्या यह है कि आप GUI थ्रेड पर ListView को अपडेट कर रहे हैं। इसका मतलब है कि ProgressBar.Value संपत्ति को बदलने के बाद आपको Application.DoEvents() पर कॉल करने की आवश्यकता होगी।

BackgroundWorker पर चलना सबसे अच्छा होगा और ProgressBar अद्यतन को संभालने के लिए ProgressChanged ईवेंट का उपयोग करना सबसे अच्छा होगा।

Here's another question एक ही विषय के बारे में।

+0

प्रगति बार मान 0 और 100 के बीच क्यों होना चाहिए? – Hemant

+0

प्रतिशत से निपटने के दौरान सुविधा के अलावा कोई कारण नहीं है ... –

+0

आप प्रगति को सेट करके प्रगति पट्टी अधिकतम बढ़ा सकते हैं। 1। अधिकतम = [int], जहां [int] एक पूर्णांक है। –

3

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

यह ध्यान रखना महत्वपूर्ण है कि केवल UI थ्रेड इंटरफ़ेस अपडेट कर सकता है। इसलिए, एक बार जब आप एक अलग थ्रेड पर चल रहे हों, तो आपको यह सुनिश्चित करने के लिए एक अतिरिक्त उछाल से गुजरना होगा कि यूआई थ्रेड पर आपका यूआई परिवर्तन संसाधित हो। यदि आप सुनिश्चित नहीं हैं कि आप किस थ्रेड पर चल रहे हैं, तो आप UIoke थ्रेड में वास्तविक हैं या नहीं, यह देखने के लिए आप InvokeRequired (यदि आपकी कक्षा एक System.Windows.Form है) का मान देख सकते हैं।

यूआई थ्रेड पर संसाधित करने के लिए अपने आदेश को प्राप्त करने के लिए, Control.Invoke() फ़ंक्शन का उपयोग यह सुनिश्चित करने के लिए करें कि आपके द्वारा काम कर रहे नियंत्रण के लिए यूआई थ्रेड पर अपडेट संसाधित हो।

नीचे मेरे नमूना कोड में मैं एक प्रतिनिधि समारोह प्रकार बना रहा हूं और पहले से ही आवंटित फ़ंक्शन घोषित कर रहा हूं .... मैंने इसे किसी भी शांत सी # 3.5 कार्यों के साथ नहीं किया है, लेकिन मुझे लगता है कि आप काम कर सकते हैं एक ही काम करने के लिए एक लम्बा अभिव्यक्ति।

private void bCreateInvoices_Click(object sender, EventArgs e) 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(CreateInvoices); 
     worker.RunWorkerAsync(this); 
    } 

// Here is the long running function that needs to update the progress bar 
public void CreateInvoices(object sernder, DoWorkEventArgs e) 
    { 
     int totalChecked = CountCheckedServiceOrders(); 
     int totalCompleted = 0; 

     foreach (...data to process...) { 
      totalCompleted++; 
      if (InvokeRequired) { 
       Invoke(new Change(OnChange), "status text", 
         totalCompleted, totalChecked);     
      } 
     } 
    } 

    // this code updates the status while a background thread works 
    private delegate void Change(string status, int complete, int total); 
    private void OnChange(string status, int complete, int total) 
    { 
     if (status == null) { 
      progressBar.Visible = false; 
      lStatus.Text = "Task complete"; 
      progressBar.Value = 0; 
     } else { 
      progressBar.Visible = true; 
      progressBar.Minimum = 0; 
      progressBar.Maximum = total; 
      progressBar.Value = complete; 
      lStatus.Text = status; 
     } 

    } 

MSDN Control.InvokeRequired manual page और कुछ अधिक जानकारी के लिए MSDN Control.Invoke manual page पर एक नजर डालें।

4

सच क्षमा करें मित्र,

वास्तव में, मैं ProgressBar.value क्षेत्र लेकिन did not उपयोग अद्यतन() विधि के लिए मूल्य assiging किया गया था। मैंने & का उपयोग किया मेरी समस्या का समाधान हो गया।

अपने सभी उत्तरों

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