Delphi中线程的概念性方法

5

2年前,Remy Lebeau 给了我有关 Delphi 线程的宝贵提示。他的回答对我非常有用,我觉得我在他的帮助下取得了很大进展。这篇帖子可以在 这里 找到。

今天,我现在面临一个关于线程的“概念性问题”。这不是关于代码的问题,而是关于应该选择哪种方法来解决某个问题的方法。我知道我们不应该询问个人意见,我只是想知道,在技术角度上,这两种方法中是否必须避免其中一种或者它们都可行。

我的应用程序在数据库中有一个唯一产品编号列表(称为 SKU)。使用这些 SKU 查询 API,我会得到一个包含有关这些产品详情的 JSON 文件。这个 JSON 文件被处理后,结果会显示在屏幕上,并保存在数据库中。因此,在一个步骤中,涉及到一个下载过程,它在一个工作线程中执行。

我看到这整个过程有两种不同的方法:

当用户点击开始按钮时,将发出一个查询,根据用户的条件构建SKU列表。然后构建Tstringlist,并为列表的每个元素启动一个线程,下载JSON,将结果发送回主线程并终止。
可以这样描述:

enter image description here

当用户点击开始按钮时,会触发一个查询,根据用户的条件构建SKU列表。不是逐个发送SKU编号到工作线程,而是将整个列表发送,并且工作线程迭代整个列表,发送结果以供显示和保存到主线程(通过同步事件)。因此,我们只有一个工作线程在终止前处理整个列表。
可以这样描述:

enter image description here

我已经编写了这两种不同的方法,它们都可以正常运行...但是我也遇到了一些缺点。
我不是专业开发人员,这只是我的兴趣爱好。在进一步推进“优化”之前,我想知道根据您的知识和经验,在技术上是否应该避免我所描述的方法之一,并说明原因。
感谢您的时间。
Mathias

1
两种方法都可以。这实际上取决于服务器是否允许同时下载多个JSON文件。如果允许,则没有理由不同时下载它们。如果不允许,则必须按顺序下载。我会进一步采用并行方法,通过限制同时运行的线程数量来控制服务器的压力,以防有大量SKU需要下载。 - Remy Lebeau
1
如果更多的提问者在准备问题时投入更多的精力,那将会非常好,点赞。 - MartynA
@RemyLebeau:再次感谢您的建议。我一定会研究线程限制。正如Dave Novo在他的回答中建议的那样,我将测量每个解决方案的持续时间并比较结果。此外,他提到线程并不是万能的解决方案,我将尝试另一种不使用线程的解决方案。 - Mathmathou
1
@MartynA:正如17世纪法国作家Nicolas BOILEAU所说:“好的构思清晰明了,表达它的话语也会轻松流畅”- 好吧,虽然这句话翻译成英文听起来不够优美,但信息很明确:如果你理解了自己的问题并能够清晰地解释,那么你获得答案的机会就更大 :) - Mathmathou
1个回答

2
在这种情况下需要考虑的另一件事是API产生JSON的延迟。例如,如果往返服务器需要30毫秒,而在服务器上创建JSON只需要0.01毫秒,则即使每个请求都在不同的线程中,查询单个JSON记录也没有多大意义。在这种情况下,更明智的做法是减少对服务器的请求次数,返回更多的数据,并将结果分配给不同的线程。
另一件事是,线程并不是解决每个问题的方法。我会质疑为什么需要将每个sku分成单个线程。每个单独的线程运行多长时间以及每个线程处理多少处理量?总的来说,为每个线程创建大量线程,让每个线程工作只有几毫秒是没有意义的。您希望线程尽可能长时间地保持活动状态,尽可能多地处理工作的数据。您不希望计算机使用大量时间来创建/销毁线程,而不是实际执行有用的工作。

1
我同意。API 应该能够返回一个 SKU 数组,而不仅仅是单个 SKU。如果您需要检索 100 个 SKU,只需发出一次查询并一次性获取这些 100 个项目即可。创建 100 个线程是一个糟糕的解决方案。创建一个发出 100 个查询的线程也不好。 - Olivier
创建线程也会消耗性能。如果可能的话,请设计您的应用程序以重复使用现有的线程,而不是在它们完成工作后总是终止它们。请参阅https://en.wikipedia.org/wiki/Thread_pool。 - AmigoJack
@dave-novo(以及Olivier和AmigoJack):您说得很对,我做了一些计算,在创建和终止工作线程之前,经过的时间平均为250毫秒。平均情况下,创建和销毁工作线程需要额外的80毫秒。在主线程中直接使用IDHTTP查询API服务器的平均时间为150毫秒。虽然差别不大,但这让我思考你们所说的:减少线程数,每个线程处理更多的工作,或者...至少在这个过程的某个部分不使用线程。感谢您的建议,我会朝着这个方向努力,度过一个忙碌的周末 :) - Mathmathou
@Mathmathou - 线程的创建和销毁时间小于1毫秒,而不是80毫秒。请参见https://stackoverflow.com/questions/54122189/thread-startup-speed-in-delphi。IDE会增加很多时间开销。 - Dave Novo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接