Multithreading 后台工作线程Delphi2010

Multithreading 后台工作线程Delphi2010,multithreading,delphi,udp,delphi-2010,indy,Multithreading,Delphi,Udp,Delphi 2010,Indy,有人能告诉我如何在Delphi2010中创建一个线程,它将作为待计算数据的“备用”线程(而不是在计算任务完成后终止) 我创建了一个程序,通过Indy UDPServer从外部源获取数据。IdUDPServer1UDPRead事件收集数据并调用不同的线程(取决于数据类型),但在调试程序时,我看到线程在计算后被终止,然后再次创建(创建线程需要一些时间)。 只要传入数据的频率大于CPU(或线程)可以处理的频率(数据在线程完成计算之前到达),我是否可以创建同一线程的fork线程 这是我试图编写的代码:

有人能告诉我如何在Delphi2010中创建一个线程,它将作为待计算数据的“备用”线程(而不是在计算任务完成后终止)

我创建了一个程序,通过Indy UDPServer从外部源获取数据。IdUDPServer1UDPRead事件收集数据并调用不同的线程(取决于数据类型),但在调试程序时,我看到线程在计算后被终止,然后再次创建(创建线程需要一些时间)。 只要传入数据的频率大于CPU(或线程)可以处理的频率(数据在线程完成计算之前到达),我是否可以创建同一线程的fork线程


这是我试图编写的代码:

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
    AData: TBytes;
    ABinding:TIdSocketHandle);                                             
begin   
  form1.panel2.color:=clLime;    
  ParseDelimited(IdUDPServer1.ReceiveString,'&');    
  if (Parsedelimited=1) and (Jvthread1.Terminated=true) then
    Jvthread1.Execute(self)    
  else if (Parsedelimited=2) and (Jvthread2.Terminated=true) then
    Jvthread2.Execute(self);

  Application.ProcessMessages;
  // i know this command is not very good but by removing this line the
  //gui is responding //after 2 or 3 sec
end;
问题是,JVThread1或JVThread2执行计算所需的时间大于传入的数据,我认为这个问题是由一次又一次创建线程所需的时间造成的(可能这是一个错误的推测)。尽管如此,通过将传入的UDP数据缓冲到Indy UDPServer中可以部分解决这一问题,但当我试图关闭UDPServer时,在其缓冲区完全为空(大约需要3-4秒)之前不会发生任何事情

创建线程需要一些时间

只要传入数据的频率更高,是否可以创建同一线程的fork线程

这是没有道理的。您的计算机只能同时执行尽可能多的线程(CPU数量)x(一个CPU中的内核数量)。所有其他线程都将等待它们的时间片。无论您将创建多少个线程,都只能执行很少的线程。创建更多的线程只会浪费系统资源

因此,我认为正确的方法不是终止计算数据帧的线程,而是请求下一个作业加载,如果没有立即准备好的作业,则进入睡眠状态

总的来说,我建议您也看看管道模型:将数据处理分为几个阶段

(internet)->输入队列->(N个工作线程,一些休眠线程处于活动状态)->半处理数据队列->(N个工作线程,一些休眠线程处于活动状态)->完全处理数据队列->(M个结果保存线程)

正如我上面所说的,N是受总CPU核数限制的。 M受到可用终端存储的限制。通常,它是单个硬盘上的单个数据库,因此M==1,但存储有时可能分片到不同的服务器或不同的磁盘

如果您的数据是不同类型的,您可以分叉流,以便某个阶段根据数据类型将结果输出到由不同工作池处理的两个不同队列中

诀窍是安排一个易于使用的框架,在这个框架中,线程可以很容易地进入睡眠状态,并随着输入数据的移动而自动唤醒。由于您使用的是Delphi 2010,因此OmniThread库可能是一个可行的解决方案:


此外,在阅读之后,Indy似乎没有针对许多连接应用进行优化。由于UDP是一种无会话协议,我希望为任何新连接打开一个新会话,并且可能会显示类似的性能限制


我建议您尝试在不同的平台上设计一个假服务器,并尝试对其进行过载(DDoS),以比较不同库允许的最大吞吐量。印第是一个,然后是超白细胞ICS和Ararat突触,还有Synopse mORMot。如果您将程序设计为管道模式,那么我认为您将能够轻松地将初始TCP/UDP输入阶段切换到任何其他库。但是,在编写其余代码之前,您是否能够证明您的库最适合您的应用程序目标?但是,您的初始阶段将非常简单-只接收数据并将其放入队列而不进行分析,让下一个阶段成为调度员查看接收的数据类型并将其发送到不同的处理队列

既然你的问题水平高是可以理解的,我将提供一个高水平的答案,它将为你指明正确的方向。如果您有更具体的问题,请先检查是否有其他人提出了该问题;如果没有,请随意提出新问题

无论何时实现一个线程,您都可以完全控制该线程的操作。所以,是的,如果您的线程执行方法只是执行一个计算,然后结束,那么您的线程将终止。如果您想保持线程的活动状态,只需确保该方法不会结束

最简单的方法是使用
而True do警告像这样将线程放入一个简单的无限循环实际上是非常糟糕的,因为它引入了一些严重的问题。您确实需要一个无限循环来保持线程在多个计算可用时处于活动状态;但是,您需要额外的代码来解决以下问题

  • 这样一个简单的循环只会占用处理器的核心(即使循环什么都不做)。这是一种资源浪费,可能会对其他应用程序产生负面影响。您真正想要的是线程只在实际有工作要做的时候进行处理;否则将被停止/暂停。
    • 这可以通过使用Windows API调用(或Delphi等效调用)来完成,该调用告诉线程停止,直到发生其他事情
    • 阅读以下内容:
      SleepEx
      WaitForSingleObject
      TSimpleEvent
  • 第二个严重的问题是这样的循环无法正常结束。通过优雅地结束,我们意味着execute方法可以在“清理”之后正常退出。否则,如果强制它在做某事的中间退出,则可能有资源、锁或内存分配给CA。