多线程Delphi [英] Multi Thread Delphi

查看:127
本文介绍了多线程Delphi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在delphi中遇到多线程问题。我有一个名字列表(约2.000个名字),我需要在我的网站上获取每个名称的一些数据。我的系统工作完美,除了线程控制。



我想创建10个线程,当一些线程终止时,创建另一个...直到结束列表。 / p>

  var 
Form1:TForm;
tCount:Integer; //线程数

实现

类型
TCheck =类(TThread)
public
构造函数Create(Name:string);
析构函数覆盖;
protected
procedure Execute;覆盖;
结束

MainT = class(TThread)
protected
procedure Execute;覆盖;
结束

析构函数TCheck.Destroy;
begin
Dec(tCount);
结束

程序MainT.Execute;
var
i:整数;
加载:TStringList;
begin
加载:= TStringList.Create;
Load.LoadFromFile('C:\mynames.txt');

for i:= 0 to Load.C​​ount -1 do
begin

如果tCount = 10然后//如果我们有10个线程运行...
开始
重复
睡眠(1);
,直到tCount< 10;
结束

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

end;

end; //程序结束

嗯,我没有把TCheck.Constructor放在一起,因为问题是方法我如何检查创建的线程的数量。我的意思是,我的软件停止,没有任何错误信息,有时检查500个名字,有时候150个名字...



对不起英语不好。

解决方案

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



定义你想要的消费者线程,队列深度,并从线程运行 DoSomeJob 过程。



使用字符串定义您的工作一个通用过程(在 CaptureJob 中)。



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



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

 使用
类,SyncObjs,Genericics.Collections;

键入
TMyConsumerItem = class(TThread)
private
FQueue:TThreadedQueue< TProc> ;;
FSignal:TCountDownEvent;
protected
procedure Execute;覆盖
public
构造函数创建(aQueue:TThreadedQueue< TProc> ;; aSignal:TCountdownEvent);
结束

构造函数TMyConsumerItem.Create(aQueue:TThreadedQueue< TProc>);
begin
Inherited Create(false);
Self.FreeOnTerminate:= true;
FQueue:= aQueue;
FSignal:= aSignal;
结束

程序TMyConsumerItem.Execute;
var
aProc:TProc;
begin
try
repeat
FQueue.PopItem(aProc);
如果没有分配(aProc)然后
break; //放这个线程
aProc();
直到终止;
finally
FSignal.Signal;
结束
结束

程序DoSomeJob(myListItems:TStringList);
const
cThreadCount = 10;
cMyQueueDepth = 100;
var
i:整数;
aQueue:TThreadedQueue< TProc> ;;
aCounter:TCountDownEvent;
函数CaptureJob(const aString:string):TProc;
开始
结果:=
程序
开始
//用aString
结束做一些工作;
结束
begin
aQueue:= TThreadedQueue< TProc> .Create(cMyQueueDepth);
aCounter:= TCountDownEvent.Create(cThreadCount);
尝试
为i:= 1 to cThreadCount do
TMyConsumerItem.Create(aQueue,aCounter);
for i:= 0 to myListItems.Count-1 do begin
aQueue.PushItem(CaptureJob(myListItems [i]));
结束
finally
for i:= 1 to cThreadCount do
aQueue.PushItem(nil);
aCounter.WaitFor; //等待线程完成
aCounter.Free;
aQueue.Free;
结束
结束






NB :Ken解释为什么你的初始化和线程的启动是错误的。这个提议显示出更好的结构,以更通用的方式处理这种类型的问题。


I'm having problems with multi thread in delphi. I Have a list of names (something about 2.000 names), and I need to get some data of each name in my site. My system works perfectly, except the thread control.

I want to create 10 threads, and, when some thread terminate, create another... until end of list.

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

Well, I didn't put the TCheck.Constructor because the problem is the method how I'm check the number of created threads. I mean, my software just stop, without any error message, sometimes check 500 names, sometimes 150 names...

Sorry for Bad English.

解决方案

Here is a threadsafe queue solution using generics.

Define how many consumer threads you want, the queue depth and just run the DoSomeJob procedure from a thread.

Define your job working with a string as a generic procedure (in CaptureJob).

When the queue is empty, the consumer threads will be destroyed. The DoSomeJob procedure waits until all jobs are ready. You can easily turn this into a generic worker pool, reusing the threads without destroying them. The generic structure of the job items also make them suitable to handle different kinds of work.

Note this queue works on XE2 and above. If you are on a older delphi version, look for a similar threadsafe queue as suggested in comments.

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;


NB: Ken explains why your initialization and start of threads are wrong. This proposal shows a better structure to handle this type of problems in a more generic way.

这篇关于多线程Delphi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆