简体   繁体   中英

ProgressBar not updating

I have a WPF form containing a button and a progress bar element. When I click the button it calls a function from another class that begins a background worker which is responsible for reading/writing data through a serial port to a device I am programming a windows interface for.

Previously I was using a new thread, but I decided to try a background worker, but still no luck.

What is happening is I click the button and the progress bar stays at 0% until my time consuming (10+ seconds) for loop is finished, and then the progress jumps to 100%

Any help is appreciated, thanks in advance. Below is the code for my interface logic:

private void connectButton_Click(object sender, RoutedEventArgs e) //Connect button clicked
    {
        if (!Global.isConnected)
        {
            device.readValues((string)portsOpen.SelectedValue, connectProgress);

            portsOpen.IsEnabled = false;
            connectButton.Content = "Disconnect";
        }
        else
        {
            device.disconnect();

            portsOpen.IsEnabled = true;
            connectButton.Content = "Connect";
        }
    }

And below is the code for my additional class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Controls;
using System.ComponentModel;

namespace lookoutSecurity
{
    class agentRadioRead
    {
    /*Local Variable Declarations*/
    SerialPort sp;
    BackgroundWorker worker;
    int attempt = 0;

    public string[] populateAvailablePorts() //Returns string array of open ports
    {
        String[] portsAvailable = SerialPort.GetPortNames();
        return portsAvailable;
    }

    public void readValues(string selectedPort, ProgressBar progressBar) //Function that sets up serial port and background worker
    {
        sp = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One);

        worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerAsync(progressBar);
    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Update user interface with current percentage
    {
        ProgressBar progressBar = e.UserState as ProgressBar;

        App.Current.Dispatcher.Invoke(
            System.Windows.Threading.DispatcherPriority.Send,
                new Action(
                    delegate()
                    { progressBar.Value = e.ProgressPercentage; }));
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e) //Initial starting point for reading data
    {
        startRead((ProgressBar)e.Argument);
    }

    private string sendInitial() //Sends ? and returns init ASUTTON
    {
        string init = "";
        sp.Write("?");

        for (int i = 0; i < 7; i++)
        {
            try
            {
                init += sp.ReadByte().ToString();
            }
            catch
            {
                break;
            }
        }

        return init;
    }

    private void startRead(ProgressBar progressBar) //Initializes data send and receive
    {
        sp.ReadTimeout = 5000;
        sp.Open();

        string init = sendInitial();

        if (init == Global.AGENT_RADIO)
        {
            sp.Write(Global.READ_VALUES, 0, Global.READ_VALUES.Length);

            byte key = (byte)sp.ReadByte();

            if (Global.START_COMMAND == key)
            {
                for (int i = 1; i < 2247; i++)
                {
                    object progressBarObject = new object();
                    progressBarObject = progressBar;
                    int progress = (i / 2246) * 100;
                    worker.ReportProgress(progress, progressBarObject);

                    readData(i, progressBar);
                    sp.Write(Global.GO_AHEAD, 0, Global.GO_AHEAD.Length);

                    sp.DiscardInBuffer();
                    sp.DiscardOutBuffer();
                }
            }
            else
            {
                System.Windows.MessageBox.Show("Connection Failed - Invalid Key: " + key);
                sp.Close();
            }
        }
        else
        {
            sp.Close();

            if (attempt < 3)
            {
                attempt++;
                startRead(progressBar);
            }
            else
            {
                System.Windows.MessageBox.Show("Connection Failed - Not Agent Radio: " + init);
            }
        }
    }

    private void readData(int iteration, ProgressBar progress) //Reads data for current iteration
    {
        byte value = 0;

        try
        {
            value = (byte)sp.ReadByte();
        }
        catch
        {
            sp.Close();
            Global.isConnected = false;

            if (attempt < 3)
            {
                attempt++;
                startRead(progress);
            }
            else
            {
                System.Windows.MessageBox.Show("Read Timeout - Value Number: " + iteration);
                App.Current.Shutdown();
            }
        }

        if (iteration > 0 && iteration < 385) //read schedule
        {
            double pos = (iteration - 1) / 48;

            int i = (int)Math.Floor(pos);
            int j = (iteration - 1) - (i * 48);

            Live.schedule[i, j] = value;
        }

        if (iteration > 384 && iteration < 1285) //read alarm history
        {
            double pos = (iteration - 385) / 9;

            int i = (int)Math.Floor(pos);
            int j = (iteration - 385) - (i * 9);

            Live.alarms[i, j] = value;
        }

        if (iteration > 1284 && iteration < 1345) //read error log
        {
            double pos = (iteration - 1285) / 6;

            int i = (int)Math.Floor(pos);
            int j = (iteration - 1285) - (i * 6);

            Live.errors[i, j] = value;
        }

        if (iteration > 1344 && iteration < 1945) //read voltage history
        {
            double pos = (iteration - 1345) / 6;

            int i = (int)Math.Floor(pos);
            int j = (iteration - 1345) - (i * 6);

            Live.voltage[i, j] = value;
        }

        if (iteration > 1944 && iteration < 1973) //read holidays
        {
            Live.holidays[iteration - 1945] = value;
        }

        if (iteration > 1972 && iteration < 2168) //read message sequences
        {
            double pos = (iteration - 1973) / 15;

            int i = (int)Math.Floor(pos);
            int j = (iteration - 1973) - (i * 15);

            Live.messages[i, j] = value;
        }

        if (iteration > 2167 && iteration < 2196) //read message info
        {
            Live.recordings[iteration - 2168] = value;
        }

        if (iteration > 2195 && iteration < 2246) //read sysval
        {
            Live.sysval[iteration - 2196] = value;
        }

        if (iteration == 2246 && value == Global.FINISH_COMMAND)
        {
            System.Windows.MessageBox.Show("All values from the device have been received.", "Data Received", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);

            Global.isConnected = true;
        }
    }

    public void disconnect() //Disconnects device
    {
        if (Global.isConnected == true)
        {
            sp.Write(Global.EXIT_PROGRAM, 0, Global.EXIT_PROGRAM.Length);
            Global.isConnected = false;
        }
    }
}
}

Your problem is here:

int progress = (i / 2246) * 100;

i/2246 will give an int, which will be truncated to zero (because i runs from 0 to < 2246), which * 100 gives zero. Until your loop ends, when i = 2246 and 2246 / 2446 * 100 = 100.

I've fallen for that before myself. You need to cast i to a float (or double) so that it does floating point division instead of integer division. Then you'll need to cast everything back to an int since progress is an int.

Something like:

int progress = (int)((float)i/2246.0) * 100;

That is mainly due to the following:

int progress = (i / 2246) * 100;

progress is always 0 until i>2246 and that is why you get a progress value of 0 until the last loop iteration where progress is equal to 1*100=100

You should do this instead:

int progress = (int)(((double) i / 2246.0) * 100);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM