Search code examples
multithreadingdelphidelphi-7

how to get count for terminated threads?


hello friends i have a doubt regarding thread count. i have some code written below for thread

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 thread does some work. my code works perfectly if i have only these threads in process. If there are some other threads running to then i will be in trouble getting threadscount by getthreadscount function and i will not get to know which threads are getting terminated by getthreadcount function. so how can i enhance my code for many threads working. My logic is when scannerch thread terminates it should decrement count variable and when it gets created it should increment count variable. so that it will not be any problem if other threads are terminated or not. i just want to deal with scannerch thread termination and need to get counts of instances of running threads of scannerch. so that i put count variable instead of getthreadscount and my problem will be solved


Solution

  • Well, the question is easy enough to answer. Declare a count variable in the main thread class:

    FScannerChildCount: Integer;
    

    Whenever you create a new thread, increment this variable. Whenever a thread terminates, decrement it.

    The incrementing is easy to do since you create the threads quite clearly and explicitly in the main thread code.

    As for the decrementing, you need an OnTerminate event handler for each scanner child thread instance. This executes in the context of the process main thread, rather than your MainThread thread. FWIW, MainThread is a terrible name since everyone takes main thread to mean the main process thread. Because the OnTerminate event doesn't run in the same thread as your MainThread thread, you'll need synchronization.

    When you increment the thread, use InterlockedIncrement. And when you decrement, use InterlockedDecrement.

    The OnTerminate handler might look like this:

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

    And you assign the event like any other event handler:

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

    All of this said, whilst this may be the answer to the question you asked, you are attempting to solve your problem the wrong way. You should be using a thread pool to simplify the coding and avoid the overhead of creating and destroying short lived threads.