简体   繁体   English

在后台工作程序中运行的应用程序执行期间,如何获取进度条以进行更新

[英]How to get progress bar to update DURING execution of an app running in a backgroundworker

I have found a lot of information on the Backgroundworker updating a progress bar and I have written numerous versions of this code. 我在Backgroundworker上更新进度条时发现了很多信息,并且编写了许多版本的代码。 But none of the versions has updated the progress bar DURING the time my upgrade application is running. 但是在我的升级应用程序运行期间,没有一个版本更新进度条。 Here is one of the DoWork handler versions that I have used: 这是我使用的DoWork处理程序版本之一:

 void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        updater.updater();

        int percents = 0;

        // Progress bar
        int total = 57;

        for (int i = 0; i <= total; i++)
        {
            System.Threading.Thread.Sleep(100);
            percents = (i * 100) / total;
            bw.ReportProgress(percents, i);
        }

If I run updater (my app) before ReportProgress (as shown), updater runs completely and then the progress bar updates from 0 to 100%. 如果我在ReportProgress之前运行更新程序(我的应用程序)(如图所示),则更新程序将完全运行,然后进度条将从0更新为100%。 If I place updater after the ReportProgress call, the progress bar runs and THEN updater runs. 如果我在ReportProgress调用之后放置更新程序,则进度条将运行,然后运行更新程序。 If I replace the Thread.Sleep line with updater, it runs at the 0% interval of the progress bar. 如果我用updater替换Thread.Sleep行,它将以进度栏的0%间隔运行。

Is it actually possible to have the progress bar update while a long-running app is executing in the backgroundworker? 实际上,可以在后台工作程序中运行长时间运行的应用程序时更新进度条吗? That is what the MSDN page for backgroundworker claims, but what they actually show is it running a series of short processes (Sleep) and not one long process. 那是MSDN专为背景工作人员准备的页面,但是他们实际显示的是它运行一系列短流程(Sleep)而不是一个长流程。 Most of the examples I have found on line use this format, making no reference to a longer running process that is not segmented into the ReportProgress section. 我在网上发现的大多数示例都使用这种格式,没有引用未细分为ReportProgress部分的运行时间更长的流程。

I would love to know if the backgroundworker is capable of doing this or is this a job for some other threading-type solution. 我很想知道背景工作人员是否能够做到这一点,或者这是其他线程类型解决方案的工作。

Thanks! 谢谢!

After seeing Tim's answer below, I attempted to implement an EventArg and Handler for the progress bar progress. 在看到下面Tim的答案后,我尝试为进度条进度实现EventArg和Handler。

public class FWupdater
{
    public string comPort;
    public int percentage;
    public State state;
    public string path;
    public const int ACK = 0x79;
    public const int NACK = 0x1F;

    public class PBProgressEventArgs : EventArgs
    {
        private int prog;

        public int progress
        {
            set { prog = value; }
            get { return this.prog; }
        }
    }

    public class PBProgress
    {
        public event PBProgressHandler Progress;
        public delegate void PBProgressHandler(PBProgress p, PBProgressEventArgs e);
        public void Start()
        {
            if (Progress != null)
            {
                PBProgressEventArgs progressUpdate = new PBProgressEventArgs();
                progressUpdate.progress = 0;
                Progress(this, progressUpdate);
            }
        }
    }

And then create an instance in the main program so that the backgroundworker could see it. 然后在主程序中创建一个实例,以便后台工作人员可以看到它。

PBProgress progUpdater = new PBProgress();

But I can't get the backgroundworker to see the progress percentage from the DoWork method. 但是我无法让后台工作人员从DoWork方法中查看进度百分比。

Including the updater code. 包括更新程序代码。

public void updater()
    {
        // Create a new SerialPort object.
        SerialPort _serialPort;
        _serialPort = new SerialPort(comPort, 115200, Parity.Even, 8, StopBits.One);

        // for state machine
        bool _continue = true;

        try
        {
            _serialPort.Open();

            if (_serialPort.IsOpen)
            {
                Console.WriteLine("");
                Console.WriteLine("Serial Port is Open");
                Console.WriteLine("");
            }
            else
            {
                MessageBox.Show("Serial Port is not open. Choose another port.");
            }
        }
        catch (UnauthorizedAccessException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (ArgumentOutOfRangeException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (ArgumentException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (IOException ex)
        {
            MessageBox.Show(ex.Message);
        }
        catch (InvalidOperationException ex)
        {
            MessageBox.Show(ex.Message);
        }


        // Move through states until upgrade is complete
        while (_continue)
        {
            switch (state)
            {
                case State.NORMAL:

                    // Beginning state for instance of upgrader

                    break;

                case State.WAITING_TO_UPGRADE:

                    SetUpComm( _serialPort);
                    state = State.ERASING_FIRMWARE;
                    break;

                case State.ERASING_FIRMWARE:

                    EraseFlashMemory(_serialPort);
                    state = State.UPGRADING_FIRMWARE;
                    break;

                case State.UPGRADING_FIRMWARE:

                    WriteNewAppToFlash(_serialPort);
                    state = State.UPGRADE_COMPLETE;
                    break;

                case State.UPGRADE_COMPLETE:

                    JumpToNewApp(_serialPort);
                    _continue = false;
                    _serialPort.Close();
                    break;

                default:
                    break;

            } // end SWITCH (state)

        } // end WHILE (_continue) - main loop

    } // end public void updater()
      // 

    // ---- METHODS -------------------



    public void SetUpComm(SerialPort _serialPort)
    {
        int byte_read = 0x00;
        var sevenF = new byte[] { 0x7F };

        // Send 0x55 and 0xAA to peripheral input to execute SwitchToBootloader()
        var byte1 = new byte[] { 0x55 };
        var byte2 = new byte[] { 0xAA };

        _serialPort.Write(byte1, 0, 1);
        _serialPort.Write(byte2, 0, 1);

        // If in bootloader mode, where the boot pins on the board are set,
        // the device will be looking to receive 0x7F to establish contact with the host.
        // In this case, the bytes to trigger boot load from inside the firmware will be
        // ignored and the following 0x7F will serve to trigger comm set-up .

        // Wait for acknowledge byte from USART
        while (byte_read != ACK)
        {
            // Write "7F" to start communicating with Bootloader
            _serialPort.Write(sevenF, 0, 1);
            Thread.Sleep(100);

            // read ACK byte after parameters set and bootloader running
            byte_read = _serialPort.ReadByte();
        }
    }


    public void EraseFlashMemory(SerialPort _serialPort)
    {
        int byte_read = 0;
        var ff = new byte[] { 0xFF };



        Console.WriteLine("Erasing flash memory...");
        Console.WriteLine("");

        /* NOTE: the ERASE COMMAND is not supported by this device, use EXTENDED ERASE */

        // Send 0x44 and 0xBB (extended erase memory command), see AN3155
        var exeraseMem = new byte[] { 0x44 };
        var bb = new byte[] { 0xBB };

        _serialPort.Write(exeraseMem, 0, 1);
        _serialPort.Write(bb, 0, 1);

        // Receive ACK byte
        byte_read = _serialPort.ReadByte();

        if (byte_read == NACK)
        {
            //Console.WriteLine("NACK received for ERASE MEMORY start");
            //Console.WriteLine("");
        }
        ////  end sending EXTENDED ERASE COMMAND

        //---------------------------------------
        // Global erase (send 0xFFFF, and 0x00)
        //---------------------------------------
        //var globalErase = new byte[] { 0x00 };
        //_serialPort.Write(ff, 0, 1);
        //_serialPort.Write(ff, 0, 1);
        //_serialPort.Write(globalErase, 0, 1);

        // Erase all but the first page (16k)
        // send number of pages to erase, msb first [11 pages, leaving page 0]
        // *ALERT* send 10 pages (N) to erase 11, for some reason it erases N + 1, whatever...
        var num_pages_msb = new byte[] { 0x00 };
        var num_pages_lsb = new byte[] { 0x0A };
        _serialPort.Write(num_pages_msb, 0, 1);
        _serialPort.Write(num_pages_lsb, 0, 1);

        // send page numbers, 2 bytes each, msb first

        // PAGE 1
        var page01_msb = new byte[] { 0x00 }; 
        var page01_lsb = new byte[] { 0x01 }; 
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page01_lsb, 0, 1);  // 1

        // PAGE 2
        var page02_lsb = new byte[] { 0x02 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page02_lsb, 0, 1);  // 2

        // PAGE 3
        var page03_lsb = new byte[] { 0x03 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page03_lsb, 0, 1);  // 3

        // PAGE 4
        var page04_lsb = new byte[] { 0x04 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page04_lsb, 0, 1);  // 4

        // PAGE 5
        var page05_lsb = new byte[] { 0x05 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page05_lsb, 0, 1);  // 5

        // PAGE 6
        var page06_lsb = new byte[] { 0x06 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page06_lsb, 0, 1);  // 6

        // PAGE 7
        var page07_lsb = new byte[] { 0x07 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page07_lsb, 0, 1);  // 7

        // PAGE 8
        var page08_lsb = new byte[] { 0x08 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page08_lsb, 0, 1);  // 8

        // PAGE 9
        var page09_lsb = new byte[] { 0x09 };
        _serialPort.Write(page01_msb, 0, 1);  // 0
        _serialPort.Write(page09_lsb, 0, 1);  // 9

        // PAGE 10
        var page10_msb = new byte[] { 0x01 };  // 1
        var page10_lsb = new byte[] { 0x00 };  // 0
        _serialPort.Write(page10_msb, 0, 1);
        _serialPort.Write(page10_lsb, 0, 1);

        // PAGE 11
        _serialPort.Write(page10_msb, 0, 1);  // 1
        _serialPort.Write(page01_lsb, 0, 1);  // 1

        // checksum = A
        _serialPort.Write(num_pages_lsb, 0, 1);

        // Receive ACK byte
        byte_read = _serialPort.ReadByte();


        bw.ReportProgress(20);

        if (byte_read == NACK)
        {
            //Console.WriteLine("NACK received for ERASE MEMORY completed");
            //Console.WriteLine("");
        }
    }
    // -- end EXTENDED ERASE MEMORY --------------------------------------------------


    public void WriteNewAppToFlash(SerialPort _serialPort)
    {
        // For testing
        int blockCount = 0;

        int byte_read = 0;
        long checksum = 0;
        var ff = new byte[] { 0xFF };

        // ------------------------------------------------------------------------------
        // -------- WRITE MEMORY --------------------------------------------------------
        // ------------------------------------------------------------------------------

        // for Address
        int baseAddress = 0x08008000;
        int offset = 0;

        // for string from HEX file
        string line;
        string[] lineBuffer = new string[16];
        int lineCount = 0;
        int length;
        int type;
        int hexChecksum = 0;

        bool sendAddress = true;

        int counter = 0;            // Counting the number of lines in the file
        int byteCounter = 0;        // Counting nmumber of bytes in the current block

        // Create byte array with 256 bytes
        byte[] buffer256 = new byte[256];

        // Read the file and process one line at a time
        System.IO.StreamReader file = new System.IO.StreamReader(path);
        while ((line = file.ReadLine()) != null)
        {
            // Store line into a line buffer. This will allow reprocessing of all lines 
            // in a block if there is an error sending a block of 256 bytes below
            if( line[8] == '0')
            {
                lineBuffer[lineCount++] = line;
            }

            // Send  WRITE COMMAND and the next address every 256 bytes
            if (sendAddress == true)
            {
                /* 
    -------------------------------------------------------------------------------------------------------
                    SEND WRITE COMMAND
    -----------------------------------------------------------------------------------------------------*/

                do
                {
                    // Send WRITE command - 0x31 and 0xCE
                    var writeMem = new byte[] { 0x31 };
                    var ce = new byte[] { 0xCE };

                    _serialPort.Write(writeMem, 0, 1);
                    _serialPort.Write(ce, 0, 1);

                    // Receive ACK byte
                    byte_read = _serialPort.ReadByte();

                } while (byte_read != ACK);

                // -- end SEND 0x31 and 0xCE and wait for ACK -----------------------------------------

                /* 
    -------------------------------------------------------------------------------------------------------
                SEND CURRENT ADDRESS AND CHECKSUM TO FLASH MEMORY
    -----------------------------------------------------------------------------------------------------*/

                Byte[] currentAddr = BitConverter.GetBytes(baseAddress + offset);

                // Increment offset by 0x100 (256 bytes)
                offset = offset + 0x00000100;

                // Reset Checksum and XOR address
                checksum = 0;
                foreach (byte b in currentAddr)
                {
                    checksum ^= b;
                }

                Byte[] cksum = BitConverter.GetBytes(checksum);

                // Send address, MSB first, LSB last
                _serialPort.Write(currentAddr, 3, 1);
                _serialPort.Write(currentAddr, 2, 1);
                _serialPort.Write(currentAddr, 1, 1);
                _serialPort.Write(currentAddr, 0, 1);

                // Send checksum of address bytes
                _serialPort.Write(cksum, 0, 1);

                // Receive ACK byte
                byte_read = _serialPort.ReadByte();

                if (byte_read == NACK)
                {
                    // Handle 
                }
                // -- end addr or increment --------------------------------------------------------- 

                sendAddress = false;

                // Send number of bytes, always 256, the last group will be padded with 0xFF
                _serialPort.Write(ff, 0, 1);

            } // end IF for WRITE COMMAND and ADDRESS


            /* FIRST CHARACTER in HEX FILE
               The colon indicates the start of a "record"
               Remove colon from beginning of string                                             */
            line = line.Substring(1, line.Length - 1);

            // Create byte array from string for whole line from HEX file
            var bytes = GetBytesFromByteString(line).ToArray();

            // Identify RECORD TYPE of HEX line [byte 4]
            type = bytes[3];

            /* Next TWO CHARACTERS   00-data                       03-start segment address
               in HEX FILE are       01-EOF                        04-extended linear address
               the record type:      02-extended segment address   05-start linear address      */

            // BLOCK WRITE TO MEMORY
            if (type == 0)
            {
                // Length of line is stored at byte 0, in this case 0x10, or 16 bytes of data
                length = bytes[0];

                // Add data from current line to buffer of 256 bytes
                for (int i = 0; i < length; i++)
                {
                    // Stuff all bytes from line into buffer of 256 bytes
                    buffer256[byteCounter++] = bytes[4 + i];

                    // Add byte to checksum
                    hexChecksum ^= bytes[4 + i];
                }

                // When buffer is full, send block of 256 bytes and checksum, reset variables for next block
                if (byteCounter >= 255)
                {

                    // Convert checksum to a byte value
                    hexChecksum = hexChecksum ^ 0xFF;
                    byte csByte = Convert.ToByte(hexChecksum);
                    Byte[] csByte_arr = BitConverter.GetBytes(csByte);

                    // Send byte array
                    _serialPort.Write(buffer256, 0, 256);

                    // For testing
                    // Console.WriteLine("block number [{0}]", ++blockCount);

                    //send checksum
                    _serialPort.Write(csByte_arr, 0, 1);

                    //Receive ACK byte
                    byte_read = _serialPort.ReadByte();
                    Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);

                    while (byte_read != ACK)
                    {
                        Array.Clear(buffer256, 0, buffer256.Length);
                        hexChecksum = 0;
                        lineCount = 0;

                        // reprocess the previous 16 lines stored in the line buffer
                        for ( int j = 0; j < 16; j++ )
                        {
                            line = lineBuffer[j];

                            line = line.Substring(1, line.Length - 1);
                            var bytesLocal = GetBytesFromByteString(line).ToArray();

                            length = bytesLocal[0];
                            for (int i = 0; i < length; i++)
                            {
                                buffer256[byteCounter++] = bytesLocal[4 + i];
                                hexChecksum ^= bytesLocal[4 + i];
                            }
                        }

                        // Convert checksum to a byte value
                        hexChecksum = hexChecksum ^ 0xFF;
                        byte csByteLocal = Convert.ToByte(hexChecksum);
                        Byte[] csByte_arrLocal = BitConverter.GetBytes(csByteLocal);

                        // Send byte array
                        _serialPort.Write(buffer256, 0, 256);

                        //send checksum
                        _serialPort.Write(csByte_arrLocal, 0, 1);

                        //Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);
                    }

                    // Clear buffer, reset byte count, clear checksum, set flag to send write cmd/send new addr
                    Array.Clear(buffer256, 0, buffer256.Length);
                    byteCounter = 0;
                    hexChecksum = 0;
                    lineCount = 0;
                    sendAddress = true;
                }

            }  // end BLOCK WRITE TO MEMORY

            else if (type == 1)  // Marker for end of file
            {
                while (byteCounter != 0)
                {
                    // Add 0xFF to the remaining bytes in this last block of 256
                    buffer256[byteCounter++] = 0xFF;

                    // Add byte to checksum
                    hexChecksum ^= 0xFF;

                    if (byteCounter >= 255)
                    {
                        byteCounter = 0;

                        // Convert checksum to a byte value
                        hexChecksum = hexChecksum ^ 0xFF;
                        byte csByte = Convert.ToByte(hexChecksum);
                        Byte[] csByte_arr = BitConverter.GetBytes(csByte);

                        // Send byte array
                        _serialPort.Write(buffer256, 0, 256);

                        // For testing
                        // Console.WriteLine("block number [{0}]", ++blockCount);

                        //send checksum
                        _serialPort.Write(csByte_arr, 0, 1);

                        //Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);

                        if (byte_read == NACK)
                        {
                            // ?? 
                        }
                    }
                }
            }
            // end ELSE if TYPE == 1

            counter++;
        } // end WHILE loop for loading hex file

        file.Close();

        // For testing
        // Console.WriteLine("File is closed.");
        // System.Console.WriteLine("There were {0} lines.", counter);
        // Console.WriteLine("");

       // -- end WRITE MEMORY ------------------------------------------------------

    }  // end  WriteNewAppToFlash



    private void handleAppSerialError(IOException exc)
    {
        throw new NotImplementedException();
    }

    private void raiseAppSerialDataEvent(byte[] received)
    {
        throw new NotImplementedException();
    }

    public void JumpToNewApp(SerialPort _serialPort)
    {
        int byte_read = 0;
        long checksum = 0;
        var ff = new byte[] { 0xFF };
        int baseAddress = 0x08000000;


        // Jumps to flash memory 0x08000000, where the sector 0 code will perform a normal startup

        // Send 0x21 ( GO ) and complement 0xDE
        var go = new byte[] { 0x21 };
        var de = new byte[] { 0xDE };

        while (byte_read != 0x79)
        {
            _serialPort.Write(go, 0, 1);
            _serialPort.Write(de, 0, 1);

            // Receive ACK byte
            byte_read = _serialPort.ReadByte();

            if (byte_read == NACK)
            {
                //Console.WriteLine("NACK received for GO COMMAND start");
                //Console.WriteLine("");
            }
        }

        // -- end SEND GO COMMAND and wait for ACK -----------------------------------------


        Byte[] startAddr = BitConverter.GetBytes(baseAddress);

        // Reset Checksum and XOR address
        checksum = 0;
        foreach (byte b in startAddr)
        {
            checksum ^= b;
        }

        Byte[] cheksum = BitConverter.GetBytes(checksum);

        // Send first byte (msb) of address
        _serialPort.Write(startAddr, 3, 1);

        // Send second byte of address
        _serialPort.Write(startAddr, 2, 1);

        // Send third byte of address
        _serialPort.Write(startAddr, 1, 1);

        // Send last byte (lsb) of address
        _serialPort.Write(startAddr, 0, 1);

        _serialPort.Write(cheksum, 0, 1);

        Thread.Sleep(20);
        // Receive ACK byte
        byte_read = _serialPort.ReadByte();

    }  // end JUMPTONEWAPP


    // Converts a string to a byte array
    public static IEnumerable<byte> GetBytesFromByteString(string str)
    {
        for (int index = 0; index < str.Length; index += 2)
        {
            yield return Convert.ToByte(str.Substring(index, 2), 16);
        }
    }

    protected void AssertOpenPort()
    {
        //          if( !IsOpen )
        //              throw new InvalidOperationException("Serial Port is not open");
    }

} // end public class FWupdater

If you are looking for real progress, then your updater will need to raise progress as it goes. 如果您正在寻找真正的进步,那么您的更新程序将需要不断进步。 You can raise events out of updater , and subscribe to them from within worker_DoWork, and use ReportProgress to marshal it back to the UI thread for progress report: 您可以从updater引发事件,并在worker_DoWork中进行订阅,然后使用ReportProgress将其编组回UI线程以进行进度报告:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    updater.Progress += updater_Progress;
    try {
        updater.updater();
    } finally {
       updater.Progress -= updater_Progress;
    }
}
void updater_Progress(object sender, ProgressEvents evt) {
    worker.ReportProgress(evt.Percent);
}

This of course requires you to create a Progress event in your Updater class and to invoke that event as your updater method does its work. 当然,这需要您在Updater类中创建一个Progress事件,并在updater方法执行其工作时调用该事件。

BackgroundWorker does two things for you: BackgroundWorker为您做两件事:

  • Lets you run a task in a background thread so your UI thread stays responsive 使您可以在后台线程中运行任务,以便您的UI线程保持响应状态
  • Lets you easily marshal progress from the background thread to the UI thread without having to use Form.Invoke . 使您无需使用Form.Invoke即可轻松地Form.Invoke从后台线程到UI线程的Form.Invoke

The DoWork event fires in a background thread. DoWork事件在后台线程中触发。 Everything in that event handler happens in order, like normal code-- while your UI thread happily continues operating. 该事件处理程序中的所有事件均按顺序发生,就像普通代码一样,而您的UI线程愉快地继续运行。 If you want fake progress, you would do the progress updating with a timer callback from the UI thread, while the BackgroundWorker runs your updater code in the background 如果您想要虚假的进度,则可以使用UI线程中的计时器回调来进行进度更新,而BackgroundWorker在后台运行更新程序代码

The question was to get updates DURING the upgrade, so it makes sense to send out changes in percentage from the program doing the work you are trying to measure. 问题是在升级过程中要获取更新,因此有意义的是从执行您要衡量的工作的程序中发送百分比更改。 The part I was missing was supplied by @mjwills - passing the BackgroundWorker as a parameter to the updater allowed me to call ReportProgress from the updater and increment the percentage value as I wished. 我缺少的部分由@mjwills提供-将BackgroundWorker作为参数传递给更新程序,使我可以从更新程序调用ReportProgress并按需要增加百分比值。

I used the BackgroundWorker (bw) set-up pretty much as shown in MSDN. 我几乎使用了MSDN中所示的BackgroundWorker(bw)设置。 Here are the methods for the bw, which I placed in my form class. 这是bw的方法,我将它们放在表单类中。

        BackgroundWorker bw = new BackgroundWorker();

Then a button click event (shows end of method) when the client has the COM port and upgrade file selected, followed by the bw methods. 然后,当客户端选择了COM端口和升级文件时,将执行按钮单击事件(显示方法结束),然后单击bw方法。

            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

            bw.WorkerReportsProgress = true;

            bw.RunWorkerAsync();

            pbar.Maximum = 100;
            pbar.Minimum = 0;
            pbar.Value = 0;

            // Percentage will be added to the end of this line during the upgrade
            updateMsg.Content = "Upgrade in progress...     ";
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bw = sender as BackgroundWorker;
        updater.updater(bw);
    }

    void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    { 
        pbar.Value = e.ProgressPercentage;
        updateMsg.Content = String.Format("Upgrade in progress...  {0} %", e.ProgressPercentage);
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        updateMsg.Content = "Upgrade Complete. Exit window to proceed...";
    }

On the updater() side, define a percentage variable: 在updater()端,定义一个百分比变量:

public int percentage;

Add the BackgroundWorker as a parameter: 将BackgroundWorker添加为参数:

public void updater( BackgroundWorker bw ) {  <code> }

Then call ReportProgress to update the ProgressPercentage event in the bw_ProgressChanged method. 然后,调用ReportProgress以更新bw_ProgressChanged方法中的ProgressPercentage事件。 Start at 0% and increment the percent variable: 从0%开始并增加百分比变量:

bw.ReportProgress(percentage += 5); 

Later on, I change the update to single percents while writing many blocks of data to flash memory: 稍后,我将更新更改为单个百分比,同时将许多数据块写入闪存:

// update progress bar in backgroundWorker thread
   if ( blockCount % 10 == 0)
   {
       bw.ReportProgress(percentage++);
   }

I would like to thank everyone for their input and I hope this answer saves someone writing an extra thousand lines of code. 我要感谢每个人的输入,希望这个答案可以节省一些编写数千行代码的人。 I hope to receive feedback on this answer and I am still interested in alternative, better solutions. 我希望收到有关此答案的反馈,但我仍然对替代性更好的解决方案感兴趣。

You can solve it like this 你可以这样解决

BackgroundWorker worker;

public void Init()
{
    worker = new BackgroundWorker();
    worker.DoWork += Worker_DoWork;
    worker.ProgressChanged += Worker_ProgressChanged;
    worker.WorkerReportsProgress = true; // This is important
    worker.RunWorkerAsync();
}

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    // Do your update progress here...

    for (int i = 0; i <= 100; i++) // This simulates the update process
    {
        System.Threading.Thread.Sleep(100);
        worker.ReportProgress(i); // Report progress from the background worker like this
    }
}

private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Update the progress bar or other ui elements here...
    // Use the e.ProgressPercentage
}

It is absolutely ok to run the background worker for a longer period of time. 长时间运行后台工作程序绝对是可以的。 I have never experienced any problems with it, even when having one running at all time. 我从未遇到过任何问题,即使一直运行都没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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