Winforms Progress bar Does Not Update (C#)

前端 未结 4 1945
青春惊慌失措
青春惊慌失措 2020-12-03 07:57

In my program [C# + winforms]. I have progress bar & listview.

Through one method i am performing some operations & then updating data in Listview. The no o

相关标签:
4条回答
  • 2020-12-03 08:30

    It sounds like you are blocking the UI thread - i.e. you haven't released the system to do any painting.

    A hacky answer is to inject Application.DoEvents() into your code - but this is risky, and has problems with re-entrancy etc; and it is just a bit hacky.

    A better option may be to do the processing on a BackgroundWorker, periodically switching to the UI thread to update things (Control.Invoke) - but this may be tricky if you are adding lots of items to a ListView.

    Full example (although you might want to batch the UI updates - not a row at a time):

    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 讨论(0)
  • 2020-12-03 08:31

    The ProgressBar.Value must be between 0 and 100.

    My guess is that your problem is that you're updating the ListView on the GUI thread. That means you'll need to call Application.DoEvents() after changing the ProgressBar.Value property.

    It would be best to run on a BackgroundWorker and use the ProgressChanged event to handle the ProgressBar update.

    Here's another question about the same topic.

    0 讨论(0)
  • 2020-12-03 08:41

    As Marc said, you want to make sure that you spin off a new thread to do your long running computation. That way the User Interface thread (which is the one that has to do all the screen updates) can redraw the progres bar whenever you change the percent complete.

    It's important to note that only the UI thread can update the interface. So, once you are running on a separate thread, you have to go through an extra hoop to make sure that your UI change is processed on the UI thread. If you aren't sure what thread you are running on, you can check the value of InvokeRequired (if your class is a System.Windows.Form) to see if you are actualy in the UI thread.

    To get your command processed on the UI thread, use the Control.Invoke() function to make sure the update is processed on the UI thread for the control you are working with.

    In my sample code below I'm creating a delegate function type and declaring the invoked function in advance....I've not done it with any of the cool C# 3.5 functions, but I bet you could work up a lamba expression to do the same thing.

     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;
            }
    
        }
    

    Take a look at the MSDN Control.InvokeRequired manual page and the MSDN Control.Invoke manual page for some more info.

    0 讨论(0)
  • 2020-12-03 08:44

    Really Sorry Friends,

    Actually, I was assiging value to ProgressBar.value field but didnt use update() method. I used that & my problem got resolved.

    Thanks all for your replies

    0 讨论(0)
提交回复
热议问题