求助下关于C# WinForm界面刷新的一些问题,我的理解是否正确
本帖最后由 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刷新,后面直接完全不刷新了。我把窗口最小化后,想要再打开也打不开,知道最后全处理完,不假死了才能打开 个人感觉这些太涉及底层了,之前好像没听说过UI主线程等此类说法
是的,耗时操作会阻塞UI线程 当每次对一个控件进行操作,这个控件对应的Control.Refresh方法就会立即激活,也就是说,只要一操作控件,此控件就会刷新。
当Winform窗口没有操作时,UI不会执行更新操作,当控件进行修改时,会立即对此控件进行刷新。
由于界面绘制是在主线程(UI线程)完成,如果在窗口的主线程执行耗时操作,那么当需要更新UI的时候,线程阻塞,将卡死无法刷新。 需要交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEvents可以防止界面停止响应,因为winform的消息循环是通过新创建一个线程来处理的,那么假如你的某个操作比较耗时,那么消息处理得等你这个耗时操作做完了才能继续,而Application.DoEvents方法就是允许你在耗时操作的内部调用它,而去处理消息队列中的消息。像鼠标移动鼠标点击都是windows消息,如果耗时操作一直进行,那么界面就像死锁一样。
所以,每完成一步耗时操作后面加一句:
Application.DoEvent();
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
以此很容易证明,你说的第一句话就全错 不要再UI的线程上进行耗时操作,这样会造成UI无响应。
楼主的需求最合适的解决方案是
1. Background worker
2. Async/Await Pattern
ahaneo 发表于 2022-6-26 22:25
需要交出CPU控制权,让系统可以处理队列中的所有Windows消息,比如在大运算量循环内,加Application.DoEven ...
foreach(每个要处理的)
{
textbox.text = “当前处理第XX个”;
textbox.Refresh();
Application.DoEvent();
…… 处理代码
}
加上Application.DoEvent();后,界面还是卡,还是没刷新几次,就再也看不到textbox变化了 owen-666 发表于 2022-6-26 22:35
不要再UI的线程上进行耗时操作,这样会造成UI无响应。
楼主的需求最合适的解决方案是
1. Background work ...
我只是想弄清楚3个问题,不是想问怎么不阻塞UI线程。这个我知道 他说的是主体form,主体form是有现成的,需要实现的多个功能应该开启新线程,关键字:Thread,多个窗口跨线程使用变量还得在主form中关闭线程保护。多看看线程Thread的应用就能理解了。