• C#--BackgroundWorker简单使用--Chart展示数据库查询的数据


    以下是学习笔记,感谢原作者的分享

    https://blog.csdn.net/songkexin/article/details/6178540

    https://www.jb51.net/article/138586.htm

      在 WinForms 中,有时要执行耗时的操作,在该操作未完成之前操作用户界面,会导致用户界面停止响应。解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作。

    新建线程可以用 Thread 类,可以实现多线程同时操作,简单的可以通过 BackgroundWorker 类实现。

      BackgroundWorker 类允许您在单独的专用线程上运行操作。 耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。 如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用

    BackgroundWorker 类方便地解决问题。

    常用方法:

    1.RunWorkerAsync
    开始执行后台操作。引发 DoWork 事件

    2.CancelAsync
    请求取消挂起的后台操作。
    注意:这个方法是将 CancellationPending 属性设置为 true,并不会终止后台操作。在后台操作中要检查 CancellationPending 属性,来决定是否要继续执行耗时的操作。

    3.ReportProgress
    引发 ProgressChanged 事件。

    常用属性:

    1.CancellationPending
    指示应用程序是否已请求取消后台操作。
    只读属性,默认为 false,当执行了 CancelAsync 方法后,值为 true。

    2.WorkerSupportsCancellation
    指示是否支持异步取消。要执行 CancelAsync 方法,需要先设置该属性为 true。

    3.WorkerReportsProgress
    指示是否能报告进度。要执行 ReportProgress 方法,需要先设置该属性为 true。

    常用事件:

    1.DoWork
    调用 RunWorkerAsync 方法时发生。

    2.RunWorkerCompleted
    后台操作已完成、被取消或引发异常时发生。

    3.ProgressChanged
    调用 ReportProgress 方法时发生。

     

    在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。


    如果想在 DoWork 事件处理程序中和用户界面的控件通信,可在用 ReportProgress 方法。
    ReportProgress(int percentProgress, object userState),可以传递一个对象。


    ProgressChanged 事件可以从参数 ProgressChangedEventArgs 类的 UserState 属性得到这个信息对象。

    简单的程序用 BackgroundWorker 比 Thread 方便,Thread 中和用户界面上的控件通信比较麻烦,需要用委托来调用控件的 Invoke 或 BeginInvoke 方法,没有 BackgroundWorker 方便。

    有2点需要注意的:

       1、由于DoWork事件内部的代码运行在非UI线程之上,确保在 DoWork 事件处理程序中不操作任何用户界面对象。 而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。

       2、BackgroundWorker 事件不跨 AppDomain 边界进行封送处理。 请不要使用 BackgroundWorker 组件在多个 AppDomain 中执行多线程操作。

    实例应用:查询数据库的数据用Chart展示

    【1】BackgroundWorker使用步骤【1】:声明一个BackgroundWorker

            //BackgroundWorker使用步骤【1】:声明一个BackgroundWorker
            BackgroundWorker backgroundWorker = new BackgroundWorker();
    

      

    【2】BackgroundWorker使用步骤【2】:绑定事件

      窗体加载的时候

                //BackgroundWorker使用步骤【2】:绑定事件
                backgroundWorker.DoWork += BackgroundWorkerDowork;
                backgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
    

      

    【3】BackgroundWorker使用步骤【3】:Dowork事件(调用 RunWorkerAsync 方法时发生。)

            //BackgroundWorker使用步骤【3】:Dowork事件(调用 RunWorkerAsync 方法时发生。)
            private void BackgroundWorkerDowork(object sender, DoWorkEventArgs e)
            {
                //DoWork事件处理函数通过参数 e 的Argument属性获取参数
                List<DateTime> timelist = (List<DateTime>)e.Argument;//异步执行的参数,因为已经知道是List<DateTime>类型,所以强制转换
                DataTable dt = new DataTable();
    
                string sql = "select * from mydata where FDateTime >=" + "format('" + timelist[0].ToString() + "')" + "and FDateTime <=" + "format('" + timelist[1].ToString() + "')" + "and PsetName =" + "'" + psetNo + "'" + "order by ID";
                dt = this.myaccess.SelectToDataTable(sql);
    
                e.Result = dt;
            }
    

      

    【4】BackgroundWorker使用步骤【4】:RunWorkerCompleted事件(当DoWork事件处理完成之后,将会触发该事件)

            //BackgroundWorker使用步骤【4】:RunWorkerCompleted事件(当DoWork事件处理完成之后,将会触发该事件)
            private void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                DataTable dt = (DataTable) e.Result;//e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值
                dtSearchData = dt;
    
                #region 拧紧趋势曲线显示
    
    
                #region 测试1:没有解决X轴时间不连续,X轴刻度不均分的问题
    
                //this.chart3.DataSource = dt;
                //this.chart3.Series["CPK"].XValueMember = "FDateTime";//这个FDateTime是时间格式,X轴刻度不是均分的
                ////this.chart1.Series["实时趋势"].XValueMember = "FAngle";//这个FAngle不是时间格式的,X轴刻度是等间距的
                //this.chart3.Series["CPK"].YValueMembers = "FTorque";
    
                #endregion
    
                #region 测试2:没有解决X轴时间不连续,X轴刻度不均分的问题
    
                //for (int i = 0; i < dt.Rows.Count; i++)
                //{
                //    chart3.Series[0].Points.AddXY(dt.Rows[i]["FDateTime"], dt.Rows[i]["FTorque"]);
                //}
    
                #endregion
    
                #region 测试3:解决X轴时间不连续,X轴刻度不均分的问题
    
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    chart1.Series[0].Points.AddXY(dt.Rows[i]["FDateTime"].ToString(), dt.Rows[i]["FTorque"].ToString());
                }
    
                #endregion
    
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    chart2.Series[0].Points.AddXY(dt.Rows[i]["FDateTime"].ToString(), dt.Rows[i]["FTorque"].ToString());
                }
                #endregion
    
                #region CPK计算显示
    
                List<float> floatList = new List<float>();
    
                for (int i = 1; i < dt.Rows.Count; i++)
                {
                    string strTorque = dt.Rows[i]["FTorque"].ToString(); //没有包含中文字符
                    if (!StringHelper.HasChinese(strTorque)) //如果没有中文
                    {
                        floatList.Add(Convert.ToSingle(strTorque));
                    }
                }
    
                float[] floatArray = new float[floatList.Count];
                floatArray = floatList.ToArray();
    
                try
                {
                    this.txt_torqueMax.Text = dt.Rows[0]["FTorqueMax"].ToString();//如果dt没收数据,这里会报错
                    this.txt_torqueMin.Text = dt.Rows[0]["FTorqueMin"].ToString();
                }
                catch (Exception)
                {
                    MessageBox.Show("当前程序号没有数据");
                }
    
                try
                {
                    UpperLimit = Convert.ToSingle(this.txt_torqueMax.Text.ToString());
                    LowerLimit = Convert.ToSingle(this.txt_torqueMin.Text.ToString());
                }
                catch 
                {
                    
                    return;
                }
    
                float f = new CpkHepler().getCPK(floatArray, UpperLimit, LowerLimit);
                this.lbl_cpk1.Text = f.ToString();
    
                #endregion
    
            }
    

      

    【5】BackgroundWorker使用步骤【5】:启动worker异步操作

      按钮点击事件

            //查询按钮 开始查询
            private void btn_query_Click(object sender, EventArgs e)
            {
                psetNo = this.cmb_psetNo.Text.Trim();
                this.cmb_trendType.SelectedIndex = 1;//
                this.timer1.Enabled = false;//停止timer1的实时更新
                this.btn_Update.Text = "开始更新";
    
                DateTime t1 = Convert.ToDateTime(this.dtp_start.Text);
                DateTime t2 = Convert.ToDateTime(this.dtp_end.Text);
                if (t1 > t2)
                {
                    MessageBox.Show("开始时间必须大于结束时间", "查询提示");
                    return;
                }
    
                TimeSpan ts = t2 - t1;
                if (ts.TotalHours > 6)
                {
                    MessageBox.Show("查询范围太多", "查询提示");
                    return;
                }
                List<DateTime> time = new List<DateTime>(){t1,t2};
    
                //BackgroundWorker使用步骤【5】:启动worker异步操作
                if (!backgroundWorker.IsBusy)//如果BackgroundWorker使用步骤不在异步运行
                {
                    backgroundWorker.RunWorkerAsync(time);//RunWorkerAsync方法让worker开始工作,调用DoWork方法
                }
            }
    

      

    【6】BackgroundWorker使用步骤【6】:取消操作

      窗体关闭的时候

            private void btn_close_Click(object sender, EventArgs e)
            {
                //BackgroundWorker使用步骤【6】:取消操作
                if (backgroundWorker.WorkerSupportsCancellation == true)
                {
                    backgroundWorker.CancelAsync();//请求取消挂起的后台操作。调用该方法将使BackgroundWorker.CancellationPending属性设置为True。
                    //backgroundWorker.CancelAsync()并不会终止后台操作。在后台操作中要检查 CancellationPending 属性,来决定是否要继续执行耗时的操作。
                }
                this.Dispose();
            }
    

      

    Chart控件初始化:

            private void InitChart()
            {
                chart1.Series.Clear();
                ChartHelper.AddSeries(chart1, "曲线图", SeriesChartType.Line, Color.FromArgb(100, 46, 199, 201), Color.White, true,true);
                ChartHelper.SetTitle(chart1, "工具1", new Font("微软雅黑", 12), Docking.Bottom, Color.FromArgb(46, 199, 201));
                ChartHelper.SetStyle(chart1, Color.Transparent, Color.White);
                ChartHelper.SetLegend(chart1, Docking.Top, StringAlignment.Center, Color.Transparent, Color.White);
                ChartHelper.SetXY(chart1, "时间", "扭矩.Nm", StringAlignment.Far, Color.White, Color.White, AxisArrowStyle.None);
                this.chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
    
                chart1.Series["曲线图"].BorderWidth = 3;
                chart1.ChartAreas[0].AxisX.Enabled = AxisEnabled.False;//不显示X轴坐标
    
                chart2.Series.Clear();
                ChartHelper.AddSeries(chart2, "曲线图", SeriesChartType.Line, Color.FromArgb(100, 46, 199, 201), Color.White, true,true);
                ChartHelper.SetTitle(chart2, "工具2", new Font("微软雅黑", 12), Docking.Bottom, Color.FromArgb(46, 199, 201));
                ChartHelper.SetStyle(chart2, Color.Transparent, Color.White);
                ChartHelper.SetLegend(chart2, Docking.Top, StringAlignment.Center, Color.Transparent, Color.White);
                ChartHelper.SetXY(chart2, "时间", "扭矩.Nm", StringAlignment.Far, Color.White, Color.White, AxisArrowStyle.None);
                this.chart2.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
    
                chart2.Series["曲线图"].BorderWidth = 3;
                chart2.ChartAreas[0].AxisY.IsStartedFromZero = false;//Y轴自适应
                chart2.ChartAreas[0].AxisX.Interval = 1; //设置X轴坐标的间隔为1,解决了/X轴间隔1个显示的问题
    
                chart3.Series.Clear();
                ChartHelper.AddSeries(chart3, "CPK", SeriesChartType.Line, Color.Lime, Color.FromArgb(109, 89, 71), true, true);
                ChartHelper.SetStyle(chart3, Color.Transparent, Color.White);
                ChartHelper.SetLegend(chart3, Docking.Top, StringAlignment.Far, Color.Transparent, Color.FromArgb(100, 128, 206));
                ChartHelper.SetXY(chart3, "", "", StringAlignment.Far, Color.FromArgb(100, 128, 206),
                    Color.FromArgb(100, 128, 206), AxisArrowStyle.None);
    
                this.chart3.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
    
                this.chart3.ChartAreas[0].AxisY.IsStartedFromZero = false;//Y轴自适应
                chart3.ChartAreas[0].AxisX.Interval = 1; //设置X轴坐标的间隔为1,解决了/X轴间隔1个显示的问题
            }
    

      

    最终效果:

  • 相关阅读:
    Java Web三层架构设计深思
    编译C源码软件需要的工具
    Hibernate之表间关系
    CSS之颜色字体
    主流的微服务框架
    CSS布局思考
    Android创建新项目及开发
    Google工程师解析Android系统架构
    java多线程实用操作
    Spring IOC/DI/注解
  • 原文地址:https://www.cnblogs.com/baozi789654/p/14587166.html
Copyright © 2020-2023  润新知