在多线程应用程序中更新UI的最佳实践 [英] Best practice for updating UI in multi-threaded app

查看:83
本文介绍了在多线程应用程序中更新UI的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在多线程Windows桌面应用程序中,从许多其他线程更新许多UI元素的最佳方法是什么?
当前,我使用委托来创建多个临时线程. UI应该在自己的线程上而不是在主"线程上吗?队列模式会更好吗?
谢谢.

What is the best way to update many UI elements from many other threads, in a multi-threaded Windows desktop app?
Currently, I use delegates, which creates many temporary threads. Should the UI be on its own thread rather than the "main" thread? Would a queue pattern be better?
Thanks.

推荐答案

好吧,UI线程主线程,因此您可以'并没有真正使它成为另一个线程.我会假设(但不确定),当您执行Control.BeginInvoke或类似操作时,它不会创建另一个临时线程",因为带有控件的整个事情是,任何更改它们的控件都必须运行在主线程上.就运行一堆临时线程而言,这就是ThreadPool设计的目的,因此使用它应该没问题.
Well, the UI thread is the main thread, so you can''t really make it another thread. I would assume (but don''t know for sure) that when you do Control.BeginInvoke or similar, it doesn''t create another "temporary thread" since the whole thing with controls is that anything that changes them has to run on the main thread. As far as running a bunch of temporary threads, that''s what the ThreadPool was designed to do, so using it should be just fine.


执行BeginInvoke之间存在很大的差异在委托上,然后在控件上执行(将委托作为参数传递).恕我直言,这两种方法使用相同的名称是一个错误,但是已完成.

在控件上执行BeginInvoke不会创建新线程,也不会从线程池中获取一个线程,但是会而是在控件的UI线程的事件队列中发布消息.可以在事件队列中发布的消息数量没有特别限制,但是仍然应该限制将要发布到事件队列中的未处理消息的数量.否则,如果UI线程由于某种原因而被阻塞,则此类消息可能会无限制地积累.在控件更新例程的开头.当我考虑更新控件时,我将变量Threading.Interlocked.Exchange更改为1,然后查看它是否尚未为1.如果是,则对控件执行BeginInvoke.如果BeginInvoke失败,则将变量设置为2(因此控件的更新例程将知道该控件需要更新,但其他尝试更新该控件的尝试将重试BeginInvoke).

此样式假定(1)如果在更新发生之前控件的值有很多更改,则除最后一个控件外的所有控件都应被忽略; (2)可以在绘制控件时更新与控件关联的字段,但前提是在当前控件完成后执行另一次更新; (3)多余的控件更新(例如,因为在更新例程开始绘制控件之后但在采样字段值之前更改了字段)将是无害的; (4)每次值更改时更新控件都不会导致过多的CPU负载.

如果这些假设成立,则代码非常简单.如果不这样做,则情况会更加复杂.
There is a world of difference between performing BeginInvoke on a delegate, and performing it on a control (passing a delegate as a parameter). IMHO, using the same name for both methods was a mistake, but what''s done is done.

Performing BeginInvoke on a control will not create a new thread, nor take one from the thread pool, but will instead post a message in the control''s UI thread''s event queue. There is no particular limit to the number of messages that can be posted in the event queue, but one should nonetheless limit the number of unprocessed messages one will post to the event queue. Otherwise, if the UI thread gets blocked for some reason, such messages may accumulate without bound.

My particular coding style is to use an UpdateNeeded variable (declared as Integer, but functionally a Boolean) which is set to 0 at the beginning of the control''s update routine. When I''m considering updating a control, I Threading.Interlocked.Exchange the variable to 1 and see if it wasn''t already 1. If so, I perform a BeginInvoke on the control. If the BeginInvoke fails, I set the variable to 2 (so the control''s update routine will know that the control needs updating, but other attempts to update the control will retry the BeginInvoke).

This style assumes that (1) if there are many changes to a control''s value before an update takes place, all but the last should be ignored; (2) it is acceptable to update the fields associated with a control while it''s being drawn, provided that one performs another update after the current one completes; (3) a redundant control update (e.g. because a field was changed after the update routine started to draw a control, but before the field''s value was sampled) will be harmless; (4) updating controls every time the value changes will not cause excessive CPU loading.

If these assumptions hold, the code is fairly straightforward. If they do not, things are more complicated.


这篇关于在多线程应用程序中更新UI的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆