2014-09-05 2 views
-1

привет друзья У меня есть сомнения относительно количества потоков. У меня есть код, написанный ниже для нитикак получить счетчик для завершенных потоков?

Procedure Mainthread.execute; 
var 
    I : integer; 
    ScannerCh : array of ScannerChild; //array of ScannerChild 
    IpList : TStringlist; 
    IPs: Integer; //ipcount is count of iplist 
Begin 
     IpList:=TStringList.Create;//creating stringlist 
     IPs := IpList.Count; //Ipcount is given value of iplists count 
     SetLength(ScannerCh, IPs); //Setting length of scannerch as ipcount 
     I:=0; 
     Repeat 
      While getthreadscount(getcurrentprocessid) >= tcount + 1(for main thread + Scannerch threads) do //Checking if is greater than tcount(thread input) by user 
      Sleep(30); 
      ScannerCh[I]:=ScannerChild.Create(True, IpList[i]); 
      ScannerCh[I].FreeOnTerminate:=True; 

      ScannerCh[I].LvHostname := LvHosts; 
      ScannerCh[I].Resume; 

      I:=I+1; 
      Sleep(20); //Sleep after each thread is created so that threads will enter critical section properly 
     until I = IPs; 
end; 

Scannerchild нить выполняет некоторые работы. мой код работает отлично, если у меня есть только эти потоки в процессе. Если есть некоторые другие потоки, запущенные, то мне будет сложно получить threadcount с помощью функции getthreadscount, и я не узнаю, какие потоки заканчиваются функцией getthreadcount. так как я могу улучшить свой код для многих потоков. Моя логика заключается в том, когда поток scannerch завершается, он должен уменьшать переменную count, а когда она создается, она должна увеличивать счетчик. так что это не будет проблемой, если другие потоки будут прекращены или нет. я просто хочу иметь дело с прерыванием потока сканера и нужно получить количество экземпляров запущенных потоков сканера. так что я ставлю переменную count вместо getthreadscount, и моя проблема будет решена.

+0

Я слышал о TNotifyEvent, но не знаю, как его использовать –

+2

Серьезно? Метод формы Button1Click является примером TNotifyEvent. Посмотрите это в OLH. В Delphi вы можете определить свои собственные типы событий, если хотите. – MartynA

+0

@MartynA +1 Но большинство новичков * знают * «TNotifyEvent» только из двойного щелчка элемента управления и магически получая декларацию метода; o) –

ответ

1

Ну, вопрос достаточно прост, чтобы ответить. Объявите переменную счетчика в классе основной нити:

FScannerChildCount: Integer; 

При создании нового потока увеличивайте эту переменную. Всякий раз, когда поток завершается, уменьшайте его.

Приращение легко сделать, поскольку вы создаете потоки достаточно четко и явно в коде основного потока.

Что касается декрементирования, вам нужен обработчик событий OnTerminate для каждого экземпляра дочерней нити сканера. Это выполняется в контексте основного потока процесса, а не вашего потока MainThread. FWIW, MainThread - ужасное имя, так как каждый принимает основной поток, чтобы обозначить основной поток процесса. Поскольку событие OnTerminate не запускается в том же потоке, что и поток MainThread, вам потребуется синхронизация.

При добавлении нити используйте InterlockedIncrement. И когда вы уменьшаете, используйте InterlockedDecrement.

Обработчик OnTerminate может выглядеть следующим образом:

procedure MainThread.ScannerChildTerminate(Sender: TObject); 
begin 
    InterlockedDecrement(FScannerChildCount); 
end; 

И вы назначаете событие, как и любой другой обработчик событий:

ScannerCh[I] := ...; 
.... 
ScannerCh[I].OnTerminate := ScannerChildTerminate; 
.... 
ScannerCh[I].Resume; 

Все это говорит, в то время как это может быть ответом на вопрос, который вы задали, вы пытаетесь решить свою проблему неправильно. Вы должны использовать пул потоков, чтобы упростить кодирование и избежать накладных расходов на создание и уничтожение короткоживущих потоков.

Смежные вопросы