多线程Delphi

Kir*_*ito 6 delphi multithreading

我在delphi中遇到多线程问题.我有一个名单(大约有2000个名字),我需要在我的网站上获取每个名字的一些数据.除线程控制外,我的系统工作正常.

我想创建10个线程,当某个线程终止时,创建另一个...直到列表的末尾.

var
 Form1: TForm;
 tCount: Integer;  //threads count

implementation

type
 TCheck = class(TThread)
 public
  constructor Create(Name: string);
  destructor Destroy; Override;
 protected
  procedure Execute; Override;
 end;

 MainT = class(TThread)
 protected
  procedure Execute; Override;
 end;

destructor TCheck.Destroy;
begin
 Dec(tCount);
end;

procedure MainT.Execute;
var
 i: Integer;
 Load: TStringList;
begin
 Load:=TStringList.Create;
 Load.LoadFromFile('C:\mynames.txt');

 for i:= 0 to Load.Count -1 do
 begin

  if tCount = 10 then  //if we have 10 threads running...
  begin
   repeat
    Sleep(1);
   until tCount < 10;
  end;

  TCheck.Create(Load.Strings[i]);
  TCheck.Start;
  Inc(tCount);

 end;

end;  // end of procedure
Run Code Online (Sandbox Code Playgroud)

好吧,我没有放TCheck.Constructor,因为问题是我如何检查创建的线程数.我的意思是,我的软件只是停止,没有任何错误信息,有时检查500个名字,有时150个名字......

对不起英语不好.

LU *_* RD 3

这是使用泛型的线程安全队列解决方案。

\n\n

定义您想要的消费者线程数、队列深度,然后DoSomeJob从线程运行该过程。

\n\n

将使用字符串的作业定义为通用过程(在 中CaptureJob)。

\n\n

当队列为空时,消费者线程将被销毁。该DoSomeJob过程会等待,直到所有作业准备就绪。\n您可以轻松地将其转变为通用工作池,重用线程而不破坏它们。工作项目的通用结构也使它们适合处理不同类型的工作。

\n\n

请注意,此队列适用于 XE2 及更高版本。如果您使用的是较旧的 delphi 版本,请按照注释中的建议查找类似的线程安全队列。

\n\n
uses\n  Classes,SyncObjs,Generics.Collections;\n\nType\n\xc2\xa0 TMyConsumerItem = class(TThread)\n\xc2\xa0 private\n\xc2\xa0 \xc2\xa0 FQueue : TThreadedQueue<TProc>;\n\xc2\xa0 \xc2\xa0 FSignal : TCountDownEvent;\n\xc2\xa0 protected\n\xc2\xa0 \xc2\xa0 procedure Execute; override;\n\xc2\xa0 public\n\xc2\xa0 \xc2\xa0 constructor Create( aQueue : TThreadedQueue<TProc>; aSignal : TCountdownEvent);\n\xc2\xa0 end;\n\nconstructor TMyConsumerItem.Create(aQueue: TThreadedQueue<TProc>);\nbegin\n  Inherited Create(false);\n  Self.FreeOnTerminate := true;\n  FQueue := aQueue;\n  FSignal := aSignal;\nend;\n\nprocedure TMyConsumerItem.Execute;\nvar\n  aProc : TProc;\nbegin\n  try\n    repeat\n      FQueue.PopItem(aProc);\n      if not Assigned(aProc) then\n        break; // Drop this thread\n      aProc();\n    until Terminated;\n  finally\n    FSignal.Signal;\n  end;\nend;\n\nprocedure DoSomeJob(myListItems : TStringList);\nconst\n  cThreadCount = 10;\n  cMyQueueDepth = 100;\nvar\n  i : Integer;\n  aQueue : TThreadedQueue<TProc>;\n  aCounter : TCountDownEvent;\n  function CaptureJob( const aString : string) : TProc;\n  begin\n    Result :=\n      procedure\n      begin\n        // Do some job with aString\n      end;\n  end;\nbegin\n  aQueue := TThreadedQueue<TProc>.Create(cMyQueueDepth);\n  aCounter := TCountDownEvent.Create(cThreadCount);\n  try\n    for i := 1 to cThreadCount do\n      TMyConsumerItem.Create(aQueue,aCounter);\n    for i := 0 to myListItems.Count-1 do begin\n      aQueue.PushItem( CaptureJob( myListItems[i]));\n    end;\n  finally\n    for i := 1 to cThreadCount do\n      aQueue.PushItem(nil);\n    aCounter.WaitFor;  // Wait for threads to finish\n    aCounter.Free;\n    aQueue.Free;\n  end;\nend;\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

注意:Ken 解释了为什么你的初始化和线程启动是错误的。该提案展示了一种更好的结构,可以以更通用的方式处理此类问题。

\n