Programming C++Builder How to wait for other threads in multi-threaded applications?
Notice: Undefined variable: relatedArticlesCount in /home/wwwroot/codeback.net/plugins/content/tags.php on line 149

How to wait for other threads in multi-threaded applications?

If your thread must wait for another thread to finish some task, you can tell your thread to temporarily suspend execution. You can either

  1. Wait for another thread to completely finish executing, or
  2. Wait for a task to be completed.

To wait for another thread to finish executing, use the WaitFor method of that other thread. WaitFor doesn't return until the other thread terminates, either by finishing its own Execute method or by terminating due to an exception. For example, the following code waits until another thread fills a thread list object before accessing the objects in the list:

if (pListFillingThread->WaitFor())
{
  TList *pList = ThreadList1->LockList();
  for (int i = 0; i Count; i++)
    ProcessItem(pList->Items[i]);
  ThreadList1->UnlockList();
}

In the previous example, the list items were only accessed when the WaitFor method indicated that the list was successfully filled. This return value must be assigned by the Execute method of the thread that was waited for. However, because threads that call WaitFor want to know the result of thread execution, not code that calls Execute, the Execute method does not return any value. Instead, the Execute method sets the ReturnValue property. ReturnValue is then returned by the WaitFor method when it is called by other threads. Return values are integers. Your application determines their meaning.

How to wait for a task to be completed?

Sometimes, you need to wait for a thread to finish some operation rather than waiting for a particular thread to complete execution. To do this, use an event object. Event objects (TEvent) should be created with global scope so that they can act like signals that are visible to all threads.

When a thread completes an operation that other threads depend on, it calls TEvent::SetEvent. SetEvent turns on the signal, so any other thread that checks will know that the operation has completed. To turn off the signal, use the ResetEvent method.

For example, consider a situation where you must wait for several threads to complete their execution rather than a single thread. Because you don抰 know which thread will finish last, you can't simply use the WaitFor method of one of the threads. Instead, you can have each thread increment a counter when it is finished, and have the last thread signal that they are all done by setting an event.

The following code shows the end of the OnTerminate event handler for all of the threads that must complete. CounterGuard is a global critical section object that prevents multiple threads from using the counter at the same time. Counter is a global variable that counts the number of threads that have completed.

void __fastcall TDataModule::TaskThreadTerminate(TObject *Sender)
{
...
  CounterGuard->Acquire(); // lock the counter
  if (--Counter == 0)    // decrement the global counter
    Event1->SetEvent(); // signal if this is the last thread
  CounterGuard->Release(); // release the lock on the counter
}

The main thread initializes the Counter variable, launches the task threads, and waits for the signal that they are all done by calling the WaitFor method. WaitFor waits for a specified time period for the signal to be set, and returns one of the values from the following table:

Value Meaning
wrSignaled The signal of the event was set.
wrTimeout The specified time elapsed without the signal being set.
wrAbandoned The event object was destroyed before the time-out period elapsed.
wrError An error occurred while waiting.

The following shows how the main thread launches the task threads and then resumes when they have all completed:

Event1->ResetEvent(); // clear the event before launching the threads

for(int i = 0; i < Counter; i++)
  new TaskThread(false); // create and launch task threads
if (Event1->WaitFor(20000) != wrSignaled)
  throw Exception;
// now continue with the main thread, all task threads have finished

Note: If you do not want to stop waiting for an event after a specified time period, pass the WaitFor method a parameter value of INFINITE. Be careful when using INFINITE, because your thread will hang if the anticipated signal is never received.


Add comment


Security code
Refresh

Programming - C++Builder