多线程UI api会是什么样的,它会提供什么样的优势?

时间:2009-07-30 17:18:45

标签: api user-interface language-agnostic

或者,等效地,您将如何设计这样的API。预期/示例用法也是说明性的。

我的好奇心直接来自于answer的评论(以及随后的编辑)。过去类似的questions/discussions提供了一些实际问题的灵感。

执行摘要:
我觉得不可能以有意义的方式使用多线程UI api,也不是特别理想。这种观点似乎有点争议,并且是一个(相对)谦虚的人,我希望看到我的方式的错误,如果它们实际上是错误的。

*在这种情况下,多线程的定义非常松散,但是对它来说它是有意义的。


由于这是非常自由的形式,我会接受在我看来哪个答案最连贯,最受支持的答案;无论我是否同意。

接受答案


**好的,或许需要更多澄清。

几乎每个严肃的应用程序都有多个线程。至少,他们会启动一个额外的线程,在响应中为UI事件做一些后台任务。

我不认为这是一个多线程用户界面。

所有UI工作仍在单线程上完成。我要说,在基本层面上,多线程UI api必须取消(以某种方式)基于线程的UI对象所有权或将事件分派给单个线程。

记住,这是关于UI api本身;而不是使用它的应用程序。

4 个答案:

答案 0 :(得分:3)

我没有看到多线程UI API与现有UI API的区别。主要区别在于:

  • (如果使用非GC语言,如C ++)对象生存期由引用计数指针包装器(如std :: tr1 :: shared_ptr)跟踪。这可以确保您不会与尝试删除对象的线程竞争。
  • 所有方法都是可重入的,线程安全的,并且保证不会阻塞事件回调(因此,在持有锁时不应调用事件回调)
  • 需要指定锁的总订单;例如,控件上的方法实现只允许调用子控件上的方法,除非调度异步回调以便稍后运行或在另一个线程上运行。

通过这两项更改,您可以将其应用于您喜欢的几乎任何GUI框架。实际上并不需要进行大规模的改变;但是,额外的锁定开销会减慢它的速度,对锁定顺序的限制将使设计自定义控件变得更复杂。

由于这通常比它的价值更麻烦,大多数GUI框架都是中间立场; UI对象通常只能从UI线程操作(某些系统,例如win32,允许有多个UI线程与单独的UI对象),并且在线程之间进行通信有一个线程安全方法来安排调用回调。 UI线程。

答案 1 :(得分:1)

大多数GUI是多线程的,至少在GUI与应用程序的其余部分在一个单独的线程中运行,并且通常还有一个用于事件处理程序的线程。这具有复杂的后端工作和同步IO的明显好处,不会使GUI处于尖锐停止状态,反之亦然。

添加更多主题往往是收益递减的主张,除非您处理多点触控或多用户等事情。但是,大多数多点触控输入似乎在驱动程序级别处理线程,因此在GUI级别通常不需要它。在大多数情况下,您只需要1:1线程与用户比率加上一些常数,具体取决于您正在做什么。

例如,预缓存线程很受欢迎。该线程可以刻录任何额外的CPU周期进行预测性缓存,以使事情运行得更快。动画线程......如果你有强化动画,但想要保持响应能力,你可以将动画置于比UI其他部分更低优先级的线程中。如上所述,事件处理程序线程也很流行,但通常透明地提供给框架的用户。

因此线程肯定有用,但为GUI生成大量线程毫无意义。但是,如果您正在编写自己的GUI框架,那么肯定必须使用线程模型来实现它。

答案 2 :(得分:0)

多线程ui应用程序没有任何问题,也没有特别之处。您所需要的只是线程之间的某种同步以及跨线程边界更新ui的方法(C#中的BeginInvoke,普通Win32应用程序中的SendMessage等)。

至于用途,你看到的几乎所有东西都是多线程的,来自互联网浏览器(他们有后台线程下载文件,而主线程负责显示下载的部分 - 再次使用大量同步)到Office应用程序(我想到了Microsoft Office中的保存功能。(祝你好运找到一个单线程的大牌游戏)。实际上,C#WinForms UI为开箱即用的UI生成了一个新线程!

您认为哪些具体内容不可取或难以实施?

答案 3 :(得分:0)

我真的没有看到任何好处。假设普通应用程序有3个主要目标:

  1. 渲染
  2. 用户输入/事件处理程序
  3. 数字运算/网络/磁盘/等
  4. 将它们分成一个线程(几个用于#3)将是非常符合逻辑的,我会称之为#1和#2 UI。

    你可以说#1已经是多线程的,并且在GPU上划分了大量的着色器处理器。我不知道在CPU上添加更多线程是否真的有用。 (至少如果你使用标准着色器,IIRC一些软件光线跟踪器和其他CGI渲染器使用多个线程 - 但我会把这些应用程序放在#3下)

    用户输入方法#2应该只是非常短,如果需要更多时间,则调用来自#3的东西,在这里添加更多线程将没有任何用处。