zoukankan      html  css  js  c++  java
  • 进度条与多线程

    为什么需要进度条?

    这里有200个左右的文件,每个文件里面有1000条数据库插入语句,总共约200 000条记录。

    在单线程情况下,执行插入时界面会失去响应,完成插入需要长达8个小时。

    不会有人认为界面没有卡死,即使是我自己写的程序,也不禁怀疑是否程序卡死。

    进度条,以及各种执行情况显示,在这种情况下真的很重要。

    我还不明白为什么界面不能刷新,即使改变控件位置等等,因此目前只能采用多线程的方式实现进度条。

    方式一

    选择控件

    一个Button及ProgressBar

    实现思路

    由UI线程负责画面刷新,另一个线程负责计算

    窗体的字段this.count就是返回给进度条的数据

    public partial class Form1 : Form
        {
            int count = 0;

    这是模拟计算的函数,当然方法体也可以替换为实际的操作。

    public void progress()//模拟执行一项耗时的操作
            {
                bool add = true;//进度条增长
                while (true)
                {
                    while (add)
                    {
                        if (this.count == 10000)//进度条上限
                        {
                            add = false;
                            break;
                        }
                        this.count += 100;//要操作的数据
                        Thread.Sleep(100);
                    }
                    while (!add)
                    {
                        if (this.count == 0)//进度条下限
                        {
                            add = true;
                            break;
                        }
                        this.count -= 100;
                        Thread.Sleep(100);
                    }
                }
            }

    在Button的点击事件中,将这个函数传递给线程

    private void button1_Click(object sender, EventArgs e)
            {
                Thread t = new Thread(new ThreadStart(progress));
                t.IsBackground = true;//在主界面关闭时此线程销毁
                t.Start();
            }

    此时点击按钮,this.count变化,但ProgressBar的Value没变,要使Value变化,得不停的给Value赋值,因此增加一个Timer

    private void timer1_Tick(object sender, EventArgs e)
            {
                this.progressBar1.Value = this.count;
            }

    现在已经实现了进度条,并且由于是单独的线程执行计算,界面并不会失去响应,任然是可互动的

    结果

    方式二

    使用委托,将progress()传递给委托,另定义call方法,使用invoke方法解决调用线程无法访问此对象的问题

    public delegate void Draw();
    Draw draw;
    
            private void button1_Click(object sender, EventArgs e)
            {
                draw = new Draw(progress);//在使用Invoke时才需要委托
                //Control.CheckForIllegalCrossThreadCalls = false;
                Thread t = new Thread(new ThreadStart(call));
                //Thread t = new Thread(new ThreadStart(progress));
                t.IsBackground = true;//在主界面关闭时此线程销毁
                t.Start();
            }
             
            public void call()
            {
                while (true)
                {
                    progressBar1.Invoke(draw);//似乎是提交给UI线程运行,UI线程在执行完自己代码后才会执行Invoke提交的代码
                }
            }

    invoke方法虽然是在新创建的线程中调用的,但根据网上一些资料以及我自己的实验,invoke应当还是由UI线程在执行,也就是说progress()由UI线程在执行,并没有解决计算与更新分离的问题,虽然这是网上大部分资料的方式

    而且这种方法界面虽然更新,但是没有响应

    改写progress()

    public void progress()//模拟执行一项耗时的操作
            {
                bool add = true;//进度条增长
                while (true)
                {
                    while (add)
                    {
                        if (this.count == 10000)
                        {
                            add = false;
                            break;
                        }
                        this.count += 100;
                        this.progressBar1.Value = this.count;//此处新增
                        Thread.Sleep(100);
                    }
                    while (!add)
                    {
                        if (this.count == 0)
                        {
                            add = true;
                            break;
                        }
                        this.count -= 100;
                        this.progressBar1.Value = this.count;//此处新增
                        Thread.Sleep(100);
                    }
                }
            }

    停止使用Timer

    结果

    虽然实现了进度条,但是与界面不能互动,窗体处于无响应状态

  • 相关阅读:
    MySQL 主从复制与读写分离概念及架构分析
    删除优先级
    原来的ALL IN ONE架构,快速的演进成为SOA架构
    a=a+1 ++a 效率比较
    Myers–Briggs_Type_Indicator 迈尔斯布里格斯类型指标(MBTI)
    事大众而数摇之,则少成功;藏大器而数徙之,则多败伤
    int float 的具体的取值范围取决于具体的机器 整数除法舍位 整形(int)也可以用于存储字符型数据
    英特尔和 Google 的 OKR 制度与我们一般所说的 KPI 有什么不同?
    Net Promoter Score
    春节问候微信群发
  • 原文地址:https://www.cnblogs.com/ggtc/p/12747817.html
Copyright © 2011-2022 走看看