RunWorkerCompleted 触发后,BackgroundWorker OnProgressChanged 仍被触发

发布于 2024-12-09 08:19:49 字数 3697 浏览 0 评论 0原文

我的应用程序使用 BackgroundWorker 将文件上传到 FTP 服务器。 一切正常,但似乎 OnProgressChanged 事件没有按应有的方式工作。

我虽然 OnProgressChanged 会在 RunWorkerCompleted 事件触发后完全完成,但事实并非如此。

就我而言,尽管 RunWorkerComplete 已触发,但 OnProgressChanged 事件仍在触发。显然,当我的文件已经完全发送到 ftp 服务器时,我的进度条仍在继续。

我在调试模式下进行了测试,发现在 RunWorkerCompleted 触发后,OnPorgressChanged 仍在工作。

我的代码在这里。

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

关于这个问题有什么想法吗? 谢谢大家

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

是伱的 2024-12-16 08:19:49

这很可能是由本机进度条组件的 Vista 更新引入的工件引起的,该组件也存在于 Windows 7 中。要查看它,请启动一个新的 Winforms 项目,然后在窗体上放置一个进度条和一个按钮。双击该按钮并使 Click 事件处理程序如下所示:

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

按 F5 并单击该按钮。请注意该栏是如何动画的,它从 0 平滑地移动到 100。大约需要一秒钟。

也许你现在明白了其中的含义,这个动画会产生滞后。换句话说,可见值始终小于编程值,除非您给它足够的时间来赶上。您不会,您会不断使用 ProgressChanged 事件处理程序更新该值。

不幸的是,他们忘记提供关闭此动画的选项。然而,有一个技巧,默认情况下禁用动画以进行递减。您可以做的是将 Value 属性设置两次,第一次设置为 value+1,然后设置为 value。该栏立即跳至编程值。它唯一的缺陷是你不能轻易跳到 100%。

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%.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文