简体   繁体   中英

BackgroundWorker OnProgressChanged still fired after RunWorkerCompleted fired

My application used BackgroundWorker for uploading a file to FTP server. Everything works ok but it seems OnProgressChanged event does not work as the way it should be.

I though that OnProgressChanged will completely finish after RunWorkerCompleted event fired, but it's not.

In my case, OnProgressChanged event is still firing though the RunWorkerComplete is fired. Obviously, my progress bar is still moving on while my file is already sent completely to the ftp server.

I tested on my debugging mode and I see that after RunWorkerCompleted Fired, OnPorgressChanged is still working.

My code is here.

 void FTP_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bw = sender as BackgroundWorker;
        try
        {
            string filename = e.Argument.ToString();
            if (filename != string.Empty)
            { 
                FileInfo fileInf = new FileInfo(filename);
                FtpWebRequest reqFTP;
                if (!IsFolderExist(_defaultDir))
                {
                    MakeDefaultDir(_defaultDir);
                }

                reqFTP = GetRequest(this._host, this._port, GetDirName(_defaultDir) + "/" + fileInf.Name, this._user, this._pass);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
                reqFTP.UseBinary = true;
                reqFTP.ContentLength = fileInf.Length;

                long FileSize = fileInf.Length;
                string FileSizeDescription = GetFileSize(FileSize);



                int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
                long SentBytes = 0;
                byte[] Buffer = new byte[ChunkSize]; 
                int BytesRead = 0;


                using (Stream requestStream = reqFTP.GetRequestStream())
                {

                    using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                         BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
                        while (BytesRead > 0)
                        {
                            try
                            {
                                if (bw.CancellationPending)
                                    return;

                                requestStream.Write(Buffer, 0, BytesRead);


                                SentBytes += BytesRead;

                                // Here is progress information
                                string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
                                bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("Exception: " + ex.ToString());
                                if (NumRetries++ < MaxRetries)
                                {
                                    fs.Position -= BytesRead;
                                }
                                else
                                {
                                    throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
                                }
                            }
                            BytesRead = fs.Read(Buffer, 0, ChunkSize);  
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            if (OnFTPError != null)
            {
                OnFTPError(this, "Error was handled in Replaced File Uploading :" + ex.Message);
            }
        }     
    }

Any ideas on this issues? Thanks guys

This is most likely caused by an artifact introduced by the Vista update for the native progress bar component, also present in Windows 7. To see it, start a new Winforms project and drop a progress bar and a button on a form. Double click the button and make the Click event handler look like this:

    private void button1_Click(object sender, EventArgs e) {
        if (progressBar1.Value == progressBar1.Maximum) progressBar1.Value = progressBar1.Minimum;
        else progressBar1.Value = progressBar1.Maximum;
    }

Press F5 and click the button. Note how the bar is animated , it smoothly moves from 0 to 100. Takes about a second.

Perhaps you see the implication now, this animation produces lag. In other words, the visible value is always less than the programmed Value unless you give it enough time to catch up. You don't, you're constantly updating the value with your ProgressChanged event handler.

Unfortunately, they forgot to provide an option to turn this animation off. There's a trick however, the animation is disabled by default for decrements. What you can do is set the Value property twice, first to value+1, then to value. The bar instantly jumps to the programmed value. The only flaw with it is that you can't easily jump to 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