gpt4 book ai didi

multithreading - 多线程德尔福

转载 作者:行者123 更新时间:2023-12-03 15:01:20 25 4
gpt4 key购买 nike

我在 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

嗯,我没有放置 TCheck.Constructor,因为问题是我检查创建的线程数的方法。我的意思是,我的软件就停止了,没有任何错误消息,有时检查 500 个名称,有时检查 150 个名称...

抱歉英语不好。

最佳答案

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

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

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

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

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

uses
Classes,SyncObjs,Generics.Collections;

Type
  TMyConsumerItem = class(TThread)
  private
    FQueue : TThreadedQueue<TProc>;
    FSignal : TCountDownEvent;
  protected
    procedure Execute; override;
  public
    constructor Create( aQueue : TThreadedQueue<TProc>; aSignal : TCountdownEvent);
  end;

constructor TMyConsumerItem.Create(aQueue: TThreadedQueue<TProc>);
begin
Inherited Create(false);
Self.FreeOnTerminate := true;
FQueue := aQueue;
FSignal := aSignal;
end;

procedure TMyConsumerItem.Execute;
var
aProc : TProc;
begin
try
repeat
FQueue.PopItem(aProc);
if not Assigned(aProc) then
break; // Drop this thread
aProc();
until Terminated;
finally
FSignal.Signal;
end;
end;

procedure DoSomeJob(myListItems : TStringList);
const
cThreadCount = 10;
cMyQueueDepth = 100;
var
i : Integer;
aQueue : TThreadedQueue<TProc>;
aCounter : TCountDownEvent;
function CaptureJob( const aString : string) : TProc;
begin
Result :=
procedure
begin
// Do some job with aString
end;
end;
begin
aQueue := TThreadedQueue<TProc>.Create(cMyQueueDepth);
aCounter := TCountDownEvent.Create(cThreadCount);
try
for i := 1 to cThreadCount do
TMyConsumerItem.Create(aQueue,aCounter);
for i := 0 to myListItems.Count-1 do begin
aQueue.PushItem( CaptureJob( myListItems[i]));
end;
finally
for i := 1 to cThreadCount do
aQueue.PushItem(nil);
aCounter.WaitFor; // Wait for threads to finish
aCounter.Free;
aQueue.Free;
end;
end;
<小时/>

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

关于multithreading - 多线程德尔福,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15622261/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com