Multithreading Delphi线程和变量

Multithreading Delphi线程和变量,multithreading,delphi,delphi-7,Multithreading,Delphi,Delphi 7,这就是我的问题,线程对我来说太混乱了,假设我有5个线程,50个或100个或更多的站点。就我对线程的了解而言,我可以让构造函数创建(link:string)并使用不同的链接启动新线程,但我需要创建与需要解析的链接数量一样多的线程。那么,如何在线程之间共享变量link,当thread one下载link listbox1.items[0]它告诉其他人数字0已经下载,下一个线程应该询问我应该下载什么链接并获得答案listbox1.items[1]等等,直到他们下载所有链接时应该终止。 谁能给我举个简单

这就是我的问题,线程对我来说太混乱了,假设我有5个线程,50个或100个或更多的站点。就我对线程的了解而言,我可以让构造函数创建(link:string)并使用不同的链接启动新线程,但我需要创建与需要解析的链接数量一样多的线程。那么,如何在线程之间共享变量link,当thread one下载link listbox1.items[0]它告诉其他人数字0已经下载,下一个线程应该询问我应该下载什么链接并获得答案listbox1.items[1]等等,直到他们下载所有链接时应该终止。
谁能给我举个简单的例子,说明如何做到这一点。线程正在扼杀我:(

你可以有一个线程安全的URL列表来处理,还有一个静态大小的工作线程池,每个线程一次从列表中获取一个未处理的URL,并对其进行处理(下载和解析)只要列表中有未处理的项目,就可以循环向列表中添加任何找到的新URL。将完成的URL保留在列表中,只标记为完成,以避免递归。

为请求URI、结果、错误消息和web查询所需的任何其他内容定义一个“TURI”类,但用于URI的组件除外访问。从TObject下降应该可以。创建、初始化100个,并将它们推送到生产者-消费者队列(TObjectQueue、TCriticalSection和一个信号灯应该可以)。从队列中挂起一些线程,循环并处理TURI实例,直到队列为空,然后它们阻塞

您没有说明需要对已处理的TURI执行什么操作-它们将需要在某个位置释放。如果您希望通知主线程,请在消息处理程序中对已完成的URI发送后消息并释放它们

终止线程?当然,如果你真的必须这样做,那么就让一些对象发出自杀信号(可能是零-线程可以在弹出队列后检查“已分配的”).当我这样做的时候,我经常会把线程放在一边,即使我在应用程序运行期间不需要再处理任何URI,也不值得键入终止它们的命令


遗憾的是,Delphi示例,恐怕还有许多教科书,除了挂起/恢复对线程的控制之外,没有什么进展,(不要这样做),以及“TThread.Synchronize”、“TThread.WaitFor”和“TThread.OnTerminate”。如果你得到这样一本教科书,就把它带到外面烧掉——你几乎学不到什么好东西。

听起来你只需要设置一个

这需要围绕读取下一个URL的代码段进行设置。为此,您通常会在代码的开头放置一个信号量,以便在任何时候只有一个线程可以进入它。信号量在代码的末尾重置。当每个新线程看到URL列表已过期时,它就会终止

信号量通常是布尔值,但它们可以是整数,例如,如果您希望允许特定数量的线程随时进入该区域

在您的例子中,您可以简单地设置一个全局布尔变量(对所有线程可见),比如“fSemaphore”

在区域的开头,线程检查标志。如果标志为false,则将其设置为true并输入区域(以获取下一个URL)。 如果为真,则循环-例如,重复睡眠(0)直到(不是fSemaphore)。 当它退出该区域时,它设置fSemaphore:=False


显然,您需要确保防范可能出现的无限循环情况…

您的最佳选择是使用。但是,您还需要提高您对线程的一般知识。您可能比购买和阅读Joe Duffy的书《Windows上的并发编程》做得更糟。要想快速而肮脏地使用InterlocatedIn作为
GetNextJob
方法的一部分,增加任务计数器。但实际上,这对于OTL来说是微不足道的。这个问题的公认答案对逻辑和示例代码进行了一些有用的讨论:OTL是否支持delphi 7,请David告诉我应该读哪些书,我找到的所有书在线程上只有10或15页在大多数情况下,它们都是一样的。谢谢,我已经告诉过你该读哪本书了。这不是一本德尔福的书,但那是无关紧要的。你需要的是并发编程的基础。遗憾的是,OTL不支持D7。我想你同时也很想读。从尝试一些建议开始,不要把多个文件集中在一起目前有多种类型的工作线程。“在列表中保留已完成的URL,只将它们标记为已完成,以避免递归”-实际上我会尽量避免这种情况,因为如果你计划启动许多这样的线程,并且应用程序可能会运行很长时间,你可能会面临这个列表变得太大,占用你的内存。我通常会制作我的线程“FreeOnTerminate”,在我释放之前,我触发了一个自定义事件“OnFinished”,提醒它的父对象它即将被释放,从而将它从列表中删除。@Jerrydrodge嗯,我仍然认为你必须以某种方式避免递归,否则你会一次又一次地处理相同的URL。