如何从另一个线程访问UI控件? [英] How to access the UI controls from another thread?

查看:100
本文介绍了如何从另一个线程访问UI控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,为了从另一个线程访问UI控件,我应该使用PostMessage().但是,PostMessage()是异步的,因此例如,如果我尝试更改"EDIT"控件的文本,则在完成后将无法删除文本缓冲区,因为我不知道窗口过程何时将完成对窗口的处理.消息.

I know that in order to access the UI controls from another thread, I should use PostMessage(). However, PostMessage() is asynchronous, so for example if I try to change the text of an "EDIT" control, I will not be able to delete the text buffer when finished because I do not know when the window procedure will finish processing the message.

这是我可以从另一个线程访问UI控件的两个想法:

So these are two ideas I can think of to access the UI controls from another thread:

  • 创建一个用户定义的消息,例如,我向UI线程发送类似的内容:"将这200行(全部存储在一个字符串中,用'\ n'分隔)插入ListViewX ",并且当UI线程收到此消息时,它将更新ListViewX,并在完成后删除字符串(在堆上分配).
  • 另一种方法是将访问UI控件的代码放在函数内部,并将函数指针发送到UI线程,然后将其调用.
  • Create a user-defined message, for example, I send to the UI thread something like: "insert these 200 rows (all stored in one string, delimited by '\n' or something) into ListViewX", and when the UI thread receives this message, it updates ListViewX, and when done, it deletes the string (which is allocated on the heap).
  • The other approach is to place the code that accesses the UI control inside of a function, and send the function pointer to the UI thread, which will then call it.

这些方法中的一种是否提供了比其他方法更多的优势,并且还有其他方法可以做到这一点吗?

Does one of these approaches provide some advantages over the other, and are there other approaches to do this?

推荐答案

我经常使用以下模式(箭头表示使用"关系):

I frequently use the following pattern (the arrows indicate a "uses" relationship):

           +---------------+                     
           | Communication |        +-----------+
      +--->+  Data Object  +<---+---+ Thread #0 |
      |    | (thread safe) |    |   +-----------+
      |    +---------------+    +---+ Thread #1 |
      |                         |   +-----------+
      |                         |     ...        
+-----+----+                    |   +-----------+
| Main (UI)|                    +---+ Thread N  |
|  Thread  |                        +-----------+
+----------+                                     

Communication Data对象是线程安全的,通常引用计数(对于非GC而言很重要-语言).该对象提供了几种典型方法(全部可选,取决于实际使用情况):

The Communication Data object is threadsafe and typically ref-counted (important for non-GC-languages). The object provides a couple of typical methods (all optional, depending on the actual use case):

  • 工作项队列
  • 需要其他任何数据交换的数据获取器/设置器
  • 要在用户界面中显示的进度信息
  • 中止/状态标志,并结合...
  • 等待事件的信号对象

因为数据对象会完全照顾自己,包括同步访问其数据,并且由于引用计数而或多或少地进行了自动清理,所以最终所有线程内容都被很好地封装到一个专用类中.我发现在各种情况下都非常方便.

Because the data object fully takes care of itself, including synchronizing access to its data, and more or less automatic cleanup due to ref-counting, you end up with all that thread stuff nicely encapsulated into one dedicated class. I found this very handy in various situations.

此外,该方法将工作线程与UI完全解耦,因此线程甚至根本不知道是否有UI以及它的外观:它是GUI吗? ?它是CLI吗?也许是网络服务?最后,由于UI线程(或其等效项)可以完全自行决定何时以及多长时间更新一次UI,因此它可以使UI保持响应.

Furthermore, the approach fully decouples the worker threads from the UI, so the threads don't even know whether or not there is an UI at all and how it looks like: is it a GUI? Is it a CLI? A web service maybe? Last not least it keeps the UI responsive, because the UI thread (or the equivalent thereof) can fully decide on its own when and how often to update the UI.

PS:可能有一个官方的GOF名称,不知道.

这篇关于如何从另一个线程访问UI控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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