Link to home
Start Free TrialLog in
Avatar of 65zgtre45rr
65zgtre45rr

asked on

Wait for thread to finish ?

Can someone write me some examples how to make that only X numbers of threads are running at the same time. For example if i have code like this https://www.experts-exchange.com/questions/21912741/CreateThread-Paramater-Problem.html (accepted answer code). How can i limit that only X numbers of threads are running at the same time. In this code there is while loop which crates threads and i want to add future of max running threads at the same time.
ASKER CERTIFIED SOLUTION
Avatar of Russell Libby
Russell Libby
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Additional note: If you add the following code to the thread function BEFORE the WaitForSingleObject line then you can see when the threads are created.

  EnterCriticalSection(Section);
  try
    WriteLn('Thread ', Integer(Parameter), ' created');
  finally LeaveCriticalSection(Section);
  end;

And when you use it, you will see that all threads are created almost immediately. So this solution will mean you have 50 threads at some point.

Also, after the line WaitForMultipleObjects you will need to add these lines:

  for I := Low(Threads) to High(Threads) do
    CloseHandle(Threads[I]);

Yes, I forgot to close all the threads... :-) For this example it's not important, though. And the TThread class will do this for you automatically.

Anyway, my approach will differ a bit from what you wanted because in my approach there is no limit to the number of created threads. It's just that most of them will be asleep and thus eat no processor time. (Just system resources.) Basically, the advantage of this is that you don't have to control the creation of the threads and put a limit there. You just put the limit in the threads themselves so your main thread doesn't have to be bothered about it.

Of course, what you could also do is wait for e.g. 5000 milliseconds instead of INFINITE. Then WaitForSingleObject will return the value WAIT_TIMEOUT instead and in my example this would mean the code inside the thread won't be executed. This would be a time-out implementation, again arranged entirely from inside the thread.

Also keep in mind that although I create the threads in a simple order, there is no way of telling in which order the threads will finish, even though all execute exactly the same code and thus should all take about the same amount of time.) The only guarantee you have is that 10 threads will be running, an d no more than 10. All other threads, while active, are all asleep. Threads that are asleep eat no CPU cycles. They are activated by the semaphore when a slot is released.
Finally, one minor warning... WaitForMultipleObjects cannot wait for more than MAXIMUM_WAIT_OBJECTS objects, which means that there's a maximum limit of 64 threads. If you have more than 64 threads then you will need this solution:

  // Now wait for all threads to finish.
  I := Low(Threads);
  while (I < High(Threads)) do
  begin
    Count := Length(Threads) + 1 - I;
    if (Count > MAXIMUM_WAIT_OBJECTS) then Count := MAXIMUM_WAIT_OBJECTS;
    WaitForMultipleObjects(Count, @Threads[I], True, INFINITE);
    I := I + Count;
  end;

You would also have to use this solution when you would be using a dynamic array for your threads. (And add a variable Count:Integer to your Var section.) Then again, you would only need this when you want to wait for all the threads to finish. And there are many other ways to do this waiting. It's just that I wanted to make this a better example.
Avatar of 65zgtre45rr
65zgtre45rr

ASKER

rllibby:
Your solutions looks nice and simple but i can't use Application.ProcessMessages becuse it freezes my form. I don't want that that is why i using threads. Can you make it on some other way.

Workshop_Alex:
It is a little complicated for me to rewrite your code for my code, so it would be nice if you could do it.

How do you plan on waiting then? Eg, you have 10 lines to process, you want 5 max threads, you spin off 5 threads to work on the first 5 lines, how do you intend to wait for one of the threads to finish so you process the remaining 5 lines?

Russell

Is there any way that wan't freez the form ?

Application.ProcessMessages (which processes the message loop) should NOT freeze the form, just the opposite in fact. You probably have something else going on in your form (code wise), and its hard to say without seeing the code you currently have.

Russell
I can't get this working. Meybe it would be uasier to write code that will do the folowing:

- create thread
- wait for this thread to finish
- create another thread

Application.ProcessMessages could freeze the mainform and whe whole application, btw. How? The dreaded deadlock situation! When you call Application.ProcessMessages then some other event might get triggered that is waiting for some flag that hasn't been set yet. Thus ProcessMessages keeps waiting for this event to finish before it sets the flag to say the event can finish. You see the impossibility in that?

Still, I myself would suggest that you use some threadpool in some way. Or else as you suggest yourself, start them one by one.
Yes this is why i want to start 1 thread and wit for this thread to finish and then start another one. Can someone write me pice of code that will wait for 1 thread to finish and then start another one.

Thank you.
Actually, you don't want to wait for the thread to finish because while your are waiting, the thread that does the waiting will be frozen...
If you create a thread by inheriting from TThread then you have an OnTerminate event which will be called right before the thread finishes. You can use that event to trigger the next event.

Unfortunately, maintaining many threads, either one by one or as a pool, can become a complex experiment. You will have to keep track of lots of possible issues. We can write some code for you based on the information you have given us but that's no use because something else in your code might cause something that will make the system fall down again. It is more useful if you understand the way threads work and then create what you need yourself. Especially considering what you are trying to do here.
I think that this OnTerminate event would be fine, could you write me something that would work with this. I think that it would look like this. OnTerminate event will set some golbal veribale to TRUE and in man form there will be code which will check for if this variable set to TRUE and then create new thread and set varibale back to false. I'm i right ? Can you write somthing like this please ?
Can someone do it ?