从this问题引出,为什么控件的某些属性(例如Label类)会导致调用Control.Handle
,但其他人不会。
我只能假设,只有在需要刷新窗口时才会选择对标签的forecolor进行更改。如果是这种情况,那么是什么使Text
属性如此重要,以至于当它的值发生变化时需要立即通知窗口?
答案 0 :(得分:4)
它与" priority"没有任何关系,它只与控件的工作方式有关。 MSDN Library记录了Control类的四个线程安全成员:InvokeRequired,BeginInvoke,Invoke和CreateGraphics。但是有一些极端情况,代码可以是线程安全的,即使它使用另一个成员。
例如,大多数控件的Text属性可以安全读取但不能写入。属性值的简单副作用存储在后备字段中,这种优化避免了必须进行昂贵的winapi调用。当您阅读该属性时,您只需获得支持字段值。但不是在你写的时候因为需要设置支持字段和来更新本机窗口。后者操作例外。
BackColor和ForeColor等属性通常是线程安全的。因为它们很简单,所以它们的setter只更新一个支持字段并调用Invalidate()。当 invalidateChildren 参数为false时,这是一个安全的函数,它只是更新"脏矩形"的窗口。稍后,导致Paint事件在UI线程上触发的那个。
哪一项优化太多了。它是线程安全的,因为它不会导致你的程序因死锁或令人讨厌的不可诊断的异常而崩溃。但是,它并不能保证用户能够看到更新后的颜色。如果您的工作线程更新BackColor并且UI线程正忙于在同时绘制窗口,那么它将使用BackColor的陈旧值,但在绘制完成时仍然将窗口标记为有效。实际上从来没有真正改变背景颜色。它不会生效,直到下次控制重新绘制自己,这可能需要很长时间。使用线程的程序中的标准事故,称为threading race。这个非常温和。但是像所有线程竞赛非常难以诊断一样,这并不会经常出错。