首页 新闻 搜索 专区 学院

C# winform进度条的刷新问题

0
[已解决问题] 解决于 2022-07-20 17:46




不知道为什么没有刷新 要等函数执行完毕之后才刷新 感觉很奇怪

刚试了下 用两条MessageBox.show()可以显示 也就是说并非函数执行完毕之后才能执行 类似于阻塞 想问下怎么解决界面刷新的问题

Miss云的主页 Miss云 | 菜鸟二级 | 园豆:208
提问于:2022-06-29 18:07

谢谢各位大佬 真好

Miss云 2周前
< >
分享
最佳答案
1
#region 旧版解决方案
        private void Button1_Click(object sender, EventArgs e) {
            ((Action)ProgressBar1).BeginInvoke((org) => { //进度条逻辑要用一个异步线程,如果直接在UI线程中循环操作,UI会出现假死,并且只显示最后一个值
                MessageBox.Show("进度条执行完毕"); //由于是异步的,这里不会阻塞
            }, null);
        }
        void ProgressBar1() {
            int i = 0;
            do {
                i++;
                //在异步线程中,不能直接操作控件,需要到控件所在的线程上通过异步委托进行操作
                label1.Invoke((Action)(() => {
                    label1.Text = i + "%";
                }));
                Thread.Sleep(50);
            } while (i < 100);
        }
        #endregion

        #region 新版async await,简单
        private async void Button2_Click(object sender, EventArgs e) {
            await ProgressBar2();
            MessageBox.Show("进度条执行完毕后才会弹出");
        }
        async Task ProgressBar2() {
            int i = 0;
            do {
                i++;
                label1.Text = i + "%";
                await Task.Delay(50);
            } while (i < 100);
        }
        #endregion
奖励园豆:5
WmW | 菜鸟二级 |园豆:269 | 2022-06-30 10:09

 

 

 

 

 

上午的时候看到了这些代码 很感谢大佬提供的这些思路和代码 很清晰

试过label标签的属性确实能够这样赋值 不过进度条并不支持 所以百度异步 如图所示 创建新线程去处理进度条值的改变 也通过打印确定了确实是两个不同的线程 但是执行的时候还是不太对

我的理解是button里的线程是主线程 而我创建的线程 也就是th 是分支线程 当分支线程完成的时候 再执行主线程 但看起来好像是 分支线程执行完毕之后会等待主线程执行完毕 最后在关闭线程释放内存的时候才会按照我的想法关闭 前后不对导致UI并没有正常刷新 强制关闭分支线程报错.....想问一下这种情况应该怎么处理

Miss云 | 园豆:208 (菜鸟二级) | 2022-06-30 17:23

@Miss云: 不是很明白你的意思,使用多线程就是为了实现异步效果,异步没有先后,多个线程是同时执行

private void Button1_Click(object sender, EventArgs e) {
            //Thread th = new Thread(AAA);
            //th.Start();
            //使用原始都得Thread可以创建一个新的线程,但是无法在该线程之心完毕后再做些什么操作
            //如果使用委托调用BeginInvoke,就能传入一个回调函数,执行该线程执行完毕后的操作
            ((Action)AAA).BeginInvoke((org => {
                MessageBox.Show("进度条走完了");
            }), null);
            MessageBox.Show("这里不会影响进度条,因为他们是不同的线程");
        }
        void AAA() {
            for (int i = 0; i < 100; i++) {
                Invoke(new Action(delegate () {
                    progressBar1.Value++;
                }));
                Thread.Sleep(50);  //这个放外面避免界面卡顿
            }
        }
        private async void Button2_Click(object sender, EventArgs e) {
            await BBB();
            MessageBox.Show("进度条走完了");
        }
        async Task BBB() {
            int i = 0;
            do {
                i++;
                progressBar1.Value = i;
                await Task.Delay(50);
            } while (i < 100);
        }
WmW | 园豆:269 (菜鸟二级) | 2022-07-01 10:03

@WmW: 这两个方法我都试了下 第一个是.net 6.0不支持委托开启 第二个的效果和我之前的效果一致

其实遇到的问题一直是 进度条的值达到了最大 但是进度条UI并没有更新 也就是看起来没满 等待弹窗弹出来之后才刷新 视觉效果就是进度条还没跑完弹窗就出来了

我需要的是进度条更新完毕(也就是进度条满了之后)再弹窗 所以本质上是同步执行 看到你的代码和注释之后了解到 进度条的值需要异步赋值刷新 所以便新建线程(th)去处理进度条的赋值问题 但是效果并不理想 依旧是 值达到最大 但是进度条控件并没有满 弹窗之后进度条才满 想问一下为什么控件没有随值的改变而更新 是需要绑定数据才会实时更新嘛

Miss云 | 园豆:208 (菜鸟二级) | 2022-07-01 14:22

@Miss云: 我也不知道什么问题了,我这边看上去没有问题

WmW | 园豆:269 (菜鸟二级) | 2022-07-01 14:58

@WmW: 有没有一种可能 就是说 Windows11 他......哈哈哈 我去虚拟机上试试 谢谢了

Miss云 | 园豆:208 (菜鸟二级) | 2022-07-01 16:51
其他回答(2)
1

是不是应该把执行的内容放到一个子线程去执行, 进度条用委托到ui线程刷新, 你现在这不都是在ui现成内呢, 委托也没用吧

百鸟朝凤 | 园豆:96 (初学一级) | 2022-06-30 09:08

我去试试 Python用太多了 这个C#完全忘完了 不刷新的原因是因为单线程来不及刷新嘛

支持(0) 反对(0) Miss云 | 园豆:208 (菜鸟二级) | 2022-06-30 09:20
1

this.invoke 放到循环外面去,你这又没用多线程,也不用invoke呀。不用线程,50个大小值,又不sleep,是瞬间完成的。
Thread th=new Thread(()=>{
this.Invoke(new Action(()=>{
for (int i = 0; i < 50; i++){
progressBar1.Value++;
Thread.Sleep(300);
}
}))
});
th.Start();

HelloLLLLL | 园豆:214 (菜鸟二级) | 2022-07-09 22:10

 

 试了一下 其实值和弹窗什么的都能正常运行 不太清楚为啥界面更新的比实际值慢一点

支持(0) 反对(0) Miss云 | 园豆:208 (菜鸟二级) | 2022-07-11 10:38

@Miss云: 你是怎么判断这个快慢的

支持(0) 反对(0) HelloLLLLL | 园豆:214 (菜鸟二级) | 2022-07-11 20:38

@HelloLLLLL: 先是视觉效果看起来进度条未满 然后弹窗就出现了 然后打断点才发现进度条的实际值已经达到最大 但是界面进度条未满 所以怀疑是界面更新问题

支持(0) 反对(0) Miss云 | 园豆:208 (菜鸟二级) | 2022-07-13 13:47

@Miss云: for循环结束的时候,加一句 progressBar1.Value=progressBar1.MaxSize

支持(0) 反对(0) HelloLLLLL | 园豆:214 (菜鸟二级) | 2022-07-14 17:54

@HelloLLLLL: 找到原因了 在UI设计界面直接更改进度条的Value值 发现有一个动画过程 也就是说进度条赋值会有一个动画效果 但是我找不到修改这个动画播放属性的地方(自己在搜资料的时候也看到了很多人吐槽这个进度条的动画效果) 于是只能回到最开始的延时操作 最后用异步等待的方式完成

 

 不过也大致弄清楚了Threading和Threading.Tasks的区别 sleep和wait的区别 还有就是二楼提供的async await 方法 确实好用 不过最好还是自定义控件 动画效果不能改太折磨人了 最后 谢谢啦 我去看看委托到底是怎么一回事

支持(0) 反对(0) Miss云 | 园豆:208 (菜鸟二级) | 2022-07-20 17:44
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册