C#开发WinForm进度条开发

C#开发WinForm进度条开发

文章目录

    • C#开发WinForm进度条开发
  • 前言
  • 实现
  • 结果
    • 补充
  • BackgroundWorker方式

前言

开发windows窗体组件,由于业务复杂需要进度条,使用ProgressBar控件。
winForm弹出窗口有两种方式:非模态窗口方式和模态窗口方式。
Show():非模态窗口方式(可以跟其他界面自由切换,而且不阻塞代码)
ShowDialog():模态窗口(必须关闭了该窗口,后面的代码才会执行,并且不能跟其他界面自由切换)。
这里面的进度条和我们开发web前端还不一样。我们知道js里,当我们弹出个进度框后,后面代码是可以执行的。在这里不行。
如果我们想用模态方式弹出框,同时还想执行后面代码。这种想法是实现不了了。只有一种办法(至少我这么认为)。将逻辑部份和组件放在一起,同时使用线程去更新UI。

实现

这里以下载文件,同时显示进度条的功能为例。

新建一个windows窗体组件,名字为DownLoadingForm
LabelProgressBar组件到窗体里。如下

C#开发WinForm进度条开发_第1张图片

去掉头部的按钮(包括最大/最小/关闭按钮):将窗体的FormBorderStyle设为None
代码如下:

using DongliCAD.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DongliCAD.component.common
{
    public partial class DownLoadingForm : Form
    {
        private string downUrl;
        private string savePath;
        /// 
        /// 
        /// 
        /// 下载url
        /// 本地保存路径
        public DownLoadingForm(string downUrl, string savePath)
        {
            this.downUrl = downUrl;
            this.savePath = savePath;
            InitializeComponent();
        }

        /// 
        /// 启动线程
        /// 
        private void startThread()
        {
            //重新开一个线程用于更新UI
            ThreadStart ts = new ThreadStart(startTime);
            Thread thread = new Thread(ts);
            thread.Name = "startTime";
            thread.Start();
        }

        private System.Timers.Timer aTimer;
        /// 
        /// 定时器
        /// 
        private void startTime()
        {
            aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new System.Timers.ElapsedEventHandler(aTimer_Elapsed);
            // 设置引发时间的时间间隔 此处设置为1秒
            aTimer.Interval = 1000;
            aTimer.Enabled = true;

            //HttpDownUtil是我的下载类。
            string resultPath = HttpDownUtil.HttpDownloadFile(downUrl, savePath);
            if (!string.IsNullOrEmpty(resultPath))
            {
                CloseTime();
            }
        }

        private delegate void SetProgressBarC(string str);
        private void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            progressBar.Invoke(new EventHandler(delegate {
                if (null != progressBar)
                {
                    int currentValue = progressBar.Value;
                    currentValue += NumberUtil.getRandNum();
                    currentValue = currentValue >= 98 ? 98 : currentValue;
                    progressBar.Value = currentValue;
                    progressLbl.Text = "下载CAD文件进度:" + currentValue + "%";
                    if (progressBar.Value >= 100)
                    {
                        if(null != aTimer) {
                            aTimer.Enabled = false;
                            aTimer.Close();
                        }
                    }
                }
            }
            ));
        }

        public void CloseTime()
        {
            if (null != aTimer)
            {
                aTimer.Enabled = false;
                aTimer.Close();
            }
            progressBar.Invoke(new EventHandler(delegate {
                if (null != progressBar)
                {
                    int currentValue = 100;
                    progressBar.Value = currentValue;
                    progressLbl.Text = "下载CAD文件进度:" + currentValue + "%";
                    Thread.Sleep(1000);
                    this.Close();
                }
            }
            ));
        }

        private void DownLoadingForm_Load(object sender, EventArgs e)
        {
            //组件初始化完成,启动线程
            startThread();
        }
    }
}

其中注意下载方法HttpDownUtil.HttpDownloadFile也必需放在新线程里执行。这里我只用了假的进度条,真实的太复杂

HttpDownUtil.csHttpDownloadFile方法:

/// 
        /// 同步下载
        /// Http下载文件
        /// 
        public static string HttpDownloadFile(string url, string path)
        {
            // 设置参数
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            if (GlobalData.Authorization.Length > 0)
            {
                request.Headers.Add("Authorization", GlobalData.Authorization);
            }
            //发送请求并获取相应回应数据
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            //直到request.GetResponse()程序才开始向目标网页发送Post请求
            Stream responseStream = response.GetResponseStream();
            //创建本地文件写入流
            Stream stream = new FileStream(path, FileMode.Create);
            byte[] bArr = new byte[1024];
            int size = responseStream.Read(bArr, 0, (int)bArr.Length);
            while (size > 0)
            {
                stream.Write(bArr, 0, size);
                size = responseStream.Read(bArr, 0, (int)bArr.Length);
            }
            stream.Close();
            responseStream.Close();
            return path;
        }

结果

结果如下:
C#开发WinForm进度条开发_第2张图片


补充

上面的下载是同步下载,如果在实时显示下载进度需要异常下载。下面代码是实时显示下载进度的代码。

/// 
    /// 下载请求信息
    /// 
    public class DownloadTmp
    {
        /// 
        /// 文件名
        /// 
        public string fileName;
        /// 
        /// 下载路径
        /// 
        public string filePath;
        /// 
        /// 下载进度回调
        /// 
        public Action loadingCallback;
        /// 
        /// 完成回调
        /// 
        public Action succeedCallback;
        /// 
        /// 失败回调
        /// 
        public Action failedCallback;
        /// 
        /// webRequest
        /// 
        public HttpWebRequest webRequest;

        public long AllContentLength;

        public long currentContentLength;
    }

using DongliCAD.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DongliCAD.component.common
{
    public partial class DownLoadingForm : Form
    {
        private string downUrl;
        private string savePath;
        private DownloadTmp downloadTmp;
        /// 
        /// 
        /// 
        /// 下载url
        /// 本地保存路径
        public DownLoadingForm(string downUrl, string savePath)
        {
            this.downUrl = downUrl;
            this.savePath = savePath;
            InitializeComponent();
        }

        /// 
        /// 启动线程
        /// 
        private void startThread()
        {
            downloadTmp = new DownloadTmp();
            downloadTmp.filePath = savePath;
            HttpDownloadZip(downUrl, ref downloadTmp);
            //HttpDownUtil.HttpDownloadFile("http://192.168.1.243:85/api/files/download/516610289672650758", savePath);
        }

  
        private void DownLoadingForm_Load(object sender, EventArgs e)
        {
            //组件初始化完成,启动线程
            startThread();
        }

        private void updateProgressBar(long allContentLength, long currentContentLength)
        {
            Debug.Write("allContentLength: " + allContentLength + ",currentContentLength: " + currentContentLength);
            progressBar.Invoke(new EventHandler(delegate {
                if (null != progressBar)
                {
                    int step = Convert.ToInt32(currentContentLength * 100 / allContentLength);
                    progressBar.Value = step;
                    progressLbl.Text = "下载CAD文件进度:" + step + "%";
                }
            }
            ));
        }

        /// 
        /// 异步回调
        /// 
        /// Result.
        private void BeginResponseCallback(IAsyncResult result)
        {
            DownloadTmp downloadInfo = (DownloadTmp)result.AsyncState;
            HttpWebRequest Request = downloadInfo.webRequest;
            HttpWebResponse Response = (HttpWebResponse)Request.EndGetResponse(result);

            if (Response.StatusCode == HttpStatusCode.OK || Response.StatusCode == HttpStatusCode.Created)
            {
                string filePath = downloadInfo.filePath;


                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                //FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
                FileStream fs = File.OpenWrite(filePath);

                Stream stream = Response.GetResponseStream();

                int count = 0;
                int num = 0;
                long AllContentLength = Response.ContentLength;
                long currentContentLength = 0;
                if (Response.ContentLength > 0)
                {
                    var buffer = new byte[2048 * 100];
                    do
                    {
                        num++;
                        count = stream.Read(buffer, 0, buffer.Length);
                        currentContentLength += count;

                        updateProgressBar(AllContentLength, currentContentLength);
                        fs.Write(buffer, 0, count);
                        if (downloadInfo.loadingCallback != null)
                        {
                            float pro = (float)fs.Length / Response.ContentLength * 100;
                            downloadInfo.loadingCallback((int)pro);
                        }
                    } while (count > 0);
                }
                fs.Close();
                Response.Close();
                if (downloadInfo.succeedCallback != null)
                {
                    downloadInfo.succeedCallback();
                }
                progressBar.Invoke(new EventHandler(delegate {
                    this.Close();
                    this.DialogResult = DialogResult.OK;
                }));
            }
            else
            {
                Response.Close();
                if (downloadInfo.failedCallback != null)
                {
                    downloadInfo.failedCallback();
                }
                progressBar.Invoke(new EventHandler(delegate {
                    this.Close();
                    this.DialogResult = DialogResult.Cancel;
                }));
            }
        }

        /// 
        /// 下载文件,异步
        /// 
        /// 下载路径
        /// 文件下载路径
        /// 
        public void HttpDownloadZip(string URL, ref DownloadTmp downloadInfo)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            if (GlobalData.Authorization.Length > 0)
            {
                request.Headers.Add("Authorization", GlobalData.Authorization);
            }
            downloadInfo.webRequest = request;
            request.BeginGetResponse(BeginResponseCallback, downloadInfo);
        }
    }
}

---------------补充2019-01-22-----------------

BackgroundWorker方式

使用BackgroundWorker做成一个上传进度条,外部传入进度值显示,对,就是和你心里想的一样的进度条。

  1. 拖拽一个BackgroundWorker到需要弹出进度条框的窗体上。
    添加代码如下
private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {

            }
            else
            {

            }
        }

        private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            startAssembly();
        }

        private void startAssembly()
        {
            //导出pdf
            this.backgroundWorker1.ReportProgress(20, "正在导出PDF...(1/6)");
            this.xExportPDF(this);
            Boolean result = false;
            this.backgroundWorker1.ReportProgress(30, "正在签出...(2/6)");
            result = this.CheckOut();
            this.backgroundWorker1.ReportProgress(40, "正在保存图纸...(3/6)");
            result = this.DoSaveTitleWBaseInfo();
            if (!result)
            {
                return;
            }
            this.SaveWorkspaceCadInfoVo();
            this.backgroundWorker1.ReportProgress(60, "正在保存BOM...(4/6)");
            result = this.SaveBom();
            if (!result)
            {
                return;
            }
            this.backgroundWorker1.ReportProgress(80, "正在签入...(5/6)");
            this.CheckIn();
            closeTimeout();
            this.backgroundWorker1.ReportProgress(100, "保存成功...(6/6)");
        }
  1. 新建一个进度条窗体,包括一个ProgressBar和一个显示文件Label,代码如下
public partial class UploadLoadingWorkerForm : Form
    {
        private BackgroundWorker backgroundWorker;
        /// 
        /// 
        /// 
        public UploadLoadingWorkerForm(BackgroundWorker backgroundWorker)
        {
            InitializeComponent();
            GlobalData.SetAutoScaleMode(this);
            this.backgroundWorker = backgroundWorker;
            this.backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            this.backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();//执行完之后,直接关闭页面
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar.Value = e.ProgressPercentage;
            this.progressLbl.Text = e.UserState.ToString();
        }

最主要的是backgroundWorker1_ProgressChanged事件处理函数,外部通过 this.backgroundWorker1.ReportProgress(30, “正在签出…(2/6)”);传值,事件处理函数负责接收并显示进度和文本。

  1. 弹出进度条
UploadLoadingWorkerForm uploadLoadingForm = new UploadLoadingWorkerForm ();
 this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件
 uploadLoadingForm = new UploadLoadingWorkerForm(this.backgroundWorker1);

你可能感兴趣的:(C#,winForm)