有关GUI应用程序中线程数的最佳实践

时间:2008-09-23 12:25:26

标签: user-interface language-agnostic

过去,我曾与许多专门编写GUI应用程序的程序员合作过。

我得到的印象是,他们几乎普遍最小化了应用程序中多线程的使用。在某些情况下,他们似乎已经竭尽全力确保他们使用单个线程。

这是常见的吗?这是gui应用程序设计的普遍接受的哲学吗?

如果是这样,为什么?

[编辑]

有许多答案说应尽量减少线程使用以降低复杂性。一般来说降低复杂性是一件好事。

但是如果你看一下对外部事件的响应至关重要的任何数量的应用程序(例如,web服务器,任意数量的嵌入式应用程序),对线程使用的态度似乎存在差异。

9 个答案:

答案 0 :(得分:5)

我认为就Windows来说,你只限于在一个线程上发生的所有GUI操作 - 由于windows消息泵工作的方式,为了增加响应性,大多数应用程序添加至少一个额外的工作线程,用于更长时间运行的任务否则阻止并使ui无反应。

线程从根本上来说很困难,所以用一个或多个线程进行思考通常会导致大量的调试工作 - 有一个引用现在就让我感到厌恶 - 如果你认为你理解线程那么你真的不“

答案 1 :(得分:5)

一般来说,GUI框架不是线程安全的。对于像Swing(Java的GUI API)这样的东西,只有一个线程可以更新UI(或者可能发生不好的事情)。只有一个线程处理调度事件。如果你有多个线程更新屏幕,你可能会得到一些丑陋的闪烁和不正确的绘图。

但这并不意味着应用程序需要是单线程的。在某种情况下,您肯定不希望出现这种情况。如果单击计算pi到1000位数的按钮,则不希望在未来几天内锁定UI并按下按钮。这就像SwingWorker之类的东西派上用场。它有两个部分:一个doInBackground(),它在一个单独的线程中运行,一个done()由doNBackground线程完成后处理更新UI的线程调用。这允许快速处理事件,或者在后台处理需要很长时间的事件,同时仍然让单个线程更新屏幕。

答案 2 :(得分:3)

我见过同样的事情。理想情况下,您应该在后台线程中执行任何将花费更长时间然后几百毫秒的操作。任何超过100毫秒的分拣机和人类可能都不会注意到差异。

我过去曾经合作过的许多GUI程序员都害怕线程,因为它们“很难”。在一些GUI框架中,例如Delphi VCL,有关于从多个线程使用VCL的警告,这往往会吓到一些人(其他人将其视为挑战;)

多线程GUI编码的一个有趣示例是BeOS API。应用程序中的每个窗口都有自己的线程。根据我的经验,这使得BeOS应用程序感觉更具响应性,但它​​确实使编程事情变得更加棘手。幸运的是,由于默认情况下BeOS被设计为多线程,所以API中有很多东西比我用过的其他操作系统更容易。

答案 3 :(得分:2)

大多数GUI框架都不是线程安全的,这意味着我必须从创建它们的同一个线程访问所有控件。尽管如此,创建工作线程以获得响应式应用程序仍然是一种很好的做法,但是您需要小心将GUI更新委派给GUI线程。

答案 4 :(得分:2)

GUI应用程序应该最小化它们使用的线程数,原因如下:

  1. 线程编程非常困难和复杂
  2. 通常,GUI应用程序最多同时执行两项操作:a)响应用户输入,b)执行后台任务(例如加载数据)以响应用户操作或预期的用户操作
  3. 通常 因此,使用多个线程增加的复杂性并不符合应用程序的需要。

    该规则当然有例外。

答案 5 :(得分:1)

GUI通常不会使用大量的线程,但它们通常会抛弃另一个线程来与某些子系统进行交互,特别是如果这些系统需要一段时间或者是非常共享的资源。

例如,如果您要打印,您通常会想要抛弃另一个线程与打印机池进行交互,因为它可能会非常繁忙一段时间并且没有理由不继续工作。

另一个例子是数据库加载,你正在与SQL服务器或类似的东西进行交互,并且由于涉及延迟,你可能想要创建另一个线程,这样你的主UI处理线程就可以继续响应命令。

答案 6 :(得分:1)

您在应用程序中拥有的线程越多,(通常)解决方案就越复杂。通过尝试最小化GUI中使用的线程数,可能存在问题的可能性较小。

另一个问题是GUI设计中最大的问题:人类。人类以 能力同时想要做多件事而臭名昭着。用户习惯于快速降低多个按钮/控件,以便更快地完成某些操作。计算机通常无法跟上这一点(这只是由GUI明显的通过使用多个线程来跟上的能力),因此为了最小化这种影响,GUI将在单个线程上以先来先服务的方式响应输入。通过这样做,GUI被迫等待,直到系统resorces是空闲的,直到它可以继续。因此,消除可能出现的所有令人讨厌的死锁情况。显然,如果程序逻辑和GUI在不同的线程上,那么这就会消失。

从个人偏好来看,我更喜欢在一个线程上保持简单但不会损害GUI的响应性。如果任务花费的时间太长,那么我会使用不同的线程,否则我会坚持只使用一个。

答案 7 :(得分:1)

正如先前的评论所说,GUI Frameworks(至少在Windows上)是单线程的,因此是单线程。另一个建议(在实践中难以编码)是将线程数限制为计算机上可用核心数。您的CPU一次只能使用一个核心执行一个操作。如果有两个线程,则必须在某个时刻进行上下文切换。如果你有太多的线程,计算机有时会花费更多的时间在线程之间交换,而不是让线程工作。

随着摩尔定律随着更多内核而发生变化,这将发生变化,并且希望编程框架能够根据程序可用的核心数量(例如TPL)更有效地使用线程。 p>

答案 8 :(得分:0)

通常,来自窗口管理器/ OS的所有窗口消息都将转到单个队列,因此将所有UI元素放在一个线程中是很自然的。如果您尝试从创建它的线程以外的线程直接访问UI元素,某些框架(如.Net)实际上会抛出异常。