吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2882|回复: 34
收起左侧

[求助] 求助下关于C# WinForm界面刷新的一些问题,我的理解是否正确

  [复制链接]
getstr88 发表于 2022-6-26 20:54
本帖最后由 getstr88 于 2022-6-26 22:10 编辑

因为接触C#没多久,且不深。最近踩了一些坑。然后看了些资料,但对winform界面绘制,还是不确定理解是否正确

所以,有几个问题,大佬们帮忙看看,我理解是否正确

1、winform界面的刷新不是执行一个代码,比如pictureBox.image = XXX,或者 textBox.text = "xxx"就立即刷新的。而是winform自己有个UI主线程,它以一定频率检测是不是有的UI被标记为需要刷新了(dirty),如果有才刷新
2、对一个控件,执行.refresh()就会立即重绘UI
3、因为winform是UI主线程,检测刷新界面,所以我如果在主线程写个非常耗时的IO操作或者干脆死循环,那么界面应该永远不刷新了


以上3个,不知理解是否正确

特别是第2条。我做过测试,就是执行一堆非常耗时的IO操作,比如处理图片并保存。
然后我代码是这样的
foreach(每个要处理的)
{
    textbox.text = “当前处理第XX个”;
    textbox.Refresh();
   …… 处理代码
   
}

前几个还能看到textbox刷新,后面直接完全不刷新了。我把窗口最小化后,想要再打开也打不开,知道最后全处理完,不假死了才能打开

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lizf2019 + 1 + 1 很好的问题,期待大佬答案

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lizf2019 发表于 2022-6-26 21:45
个人感觉这些太涉及底层了,之前好像没听说过UI主线程等此类说法
ashuaiPo 发表于 2022-6-26 22:02
Domado 发表于 2022-6-26 22:14
当每次对一个控件进行操作,这个控件对应的Control.Refresh方法就会立即激活,也就是说,只要一操作控件,此控件就会刷新。
当Winform窗口没有操作时,UI不会执行更新操作,当控件进行修改时,会立即对此控件进行刷新。
由于界面绘制是在主线程(UI线程)完成,如果在窗口的主线程执行耗时操作,那么当需要更新UI的时候,线程阻塞,将卡死无法刷新。
ahaneo 发表于 2022-6-26 22:25
需要交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEvents可以防止界面停止响应,因为winform的消息循环是通过新创建一个线程来处理的,那么假如你的某个操作比较耗时,那么消息处理得等你这个耗时操作做完了才能继续,而Application.DoEvents方法就是允许你在耗时操作的内部调用它,而去处理消息队列中的消息。像鼠标移动鼠标点击都是windows消息,如果耗时操作一直进行,那么界面就像死锁一样。
所以,每完成一步耗时操作后面加一句:
[C#] 纯文本查看 复制代码
Application.DoEvent();

 楼主| getstr88 发表于 2022-6-26 22:30
Domado 发表于 2022-6-26 22:14
当每次对一个控件进行操作,这个控件对应的Control.Refresh方法就会立即激活,也就是说,只要一操作控件, ...

兄弟,你这个样不好吧。做学问不能靠主观想象吧。你说的第一点就不对,控件不是改了就立即刷新界面的,更不会自动调用Control.Refresh

这个好证明,
private void button4_Click(object sender, EventArgs e)
        {
            label1.Text = "1111";
            label1.Refresh();
            int a = 1;
        }

打断点就一目了然,把断点打在 label1.Refresh();之前,你会发现,界面没有改变。但把断点打在int a =1这行, label1.Refresh();执行了,你就发现界面label文字改为111

以此很容易证明,你说的第一句话就全错
owen-666 发表于 2022-6-26 22:35
不要再UI的线程上进行耗时操作,这样会造成UI无响应。
楼主的需求最合适的解决方案是
1. Background worker  
2. Async/Await Pattern
 楼主| getstr88 发表于 2022-6-26 22:42
ahaneo 发表于 2022-6-26 22:25
需要交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEven ...

foreach(每个要处理的)
{
    textbox.text = “当前处理第XX个”;
    textbox.Refresh();
Application.DoEvent();
   …… 处理代码
   
}

加上Application.DoEvent();后,界面还是卡,还是没刷新几次,就再也看不到textbox变化了
 楼主| getstr88 发表于 2022-6-26 22:43
owen-666 发表于 2022-6-26 22:35
不要再UI的线程上进行耗时操作,这样会造成UI无响应。
楼主的需求最合适的解决方案是
1. Background work ...

我只是想弄清楚3个问题,不是想问怎么不阻塞UI线程。这个我知道
disllusion 发表于 2022-6-26 23:38
他说的是主体form,主体form是有现成的,需要实现的多个功能应该开启新线程,关键字:Thread,多个窗口跨线程使用变量还得在主form中关闭线程保护。多看看线程Thread的应用就能理解了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-4 01:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表