【问题标题】:ProgressBar not updating进度条不更新
【发布时间】:2012-07-12 20:30:35
【问题描述】:

我有一个 WPF 表单,其中包含一个按钮和一个进度条元素。当我单击该按钮时,它会从另一个类调用一个函数,该函数启动一个后台工作程序,该工作程序负责通过串行端口读取/写入数据到我正在为其编写 Windows 界面的设备。

之前我在使用一个新线程,但我决定尝试一个后台工作人员,但仍然没有运气。

发生的情况是我单击按钮,进度条保持在 0%,直到我的耗时(10 多秒)for 循环完成,然后进度跳到 100%

任何帮助表示赞赏,在此先感谢。下面是我的接口逻辑代码:

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

下面是我的附加课程的代码:

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

【问题讨论】:

  • 您可能希望使用(ProgressBar)e.UserState 而不是e.UserState as ProgressBaras 运算符是 VB.NET 的一个转折点,恕我直言,不应在 C# 中使用...
  • @ColeJohnson 你能解释一下为什么 as 不应该在 C# 中使用吗?
  • @ColeJohnson:as 没什么问题。这是非常好的 C#。
  • @ColeJohnson 我不同意它不应该被使用; as 适用于您不确定演员表是否会成功的情况(但如果成功了,我想采取某些行动。)不过,我实际上同意这种情况,因为演员表总是会成功。
  • 虽然您可以将i 转换为浮点类型,但您也可以先进行乘法运算并避免转换/转换问题:int progress = (i * 100) / 2246;

标签: c# wpf multithreading progress-bar backgroundworker


【解决方案1】:

你的问题在这里:

int progress = (i / 2246) * 100;

i/2246 将给出一个 int,它将被截断为零(因为 i 从 0 运行到

我之前就已经爱上了它。您需要将 i 转换为浮点数(或双精度数),以便它进行浮点除法而不是整数除法。然后你需要将所有内容都转换回一个 int,因为 progress 是一个 int。

类似:

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

【讨论】:

  • int progress = (int)((float)i/2246.0) * 100; 应该是 int progress = (int)(((float)i/2246.0) * 100); 否则它仍然会给出相同的结果 0
  • 简单的 100 * i / 2246 怎么样? (面面相觑;)
  • 为什么不使用double?更精确 == 更准确的答案。
  • @GETah:哦,我确定我不匹配或忘记了正确数量的括号。但我很确定 ((float)i/2246.0) 会给出一个浮点数,而一个浮点数 * 一个 int (即 100)会给出一个浮点数。无论哪种方式,我始终认为更多的括号不会造成伤害!
  • @ColeJohnson:我认为这应该是个玩笑?但是请你自己,这真的不会有任何区别。
【解决方案2】:

这主要是由于以下原因:

int progress = (i / 2246) * 100;

i&gt;2246 之前,进度始终为0,这就是为什么在最后一次循环迭代中进度等于1*100=100 之前,您会获得0 的进度值

你应该这样做:

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

【讨论】:

  • 认为你错过了最后一次转换回 int!
  • 也感谢您的帮助
猜你喜欢
  • 2020-11-05
  • 1970-01-01
  • 2020-10-06
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多