• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1126
  • Last Modified:

Multithreading, WaitForMultipleObjects and Variable Number of Threads

I am writing a multithreaded application in C using MSVS 2008.  Normally, to create several threads you would write the following lines of code:

HANDLE hThrds[3];

hThrds[0] = (HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID);
hThrds[1] = (HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID);
hThrds[2] = (HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID);

We would then wait for the threads to finish with the following line of code:

WaitForMultipleObjects (3, hThrds, TRUE, INFINITE);

My question is what do we do if we do not know how many threads we will create till runtime?  For example, suppose we still had the declaration

HANDLE hThrds[3];

But only created one thread.

hThrds[0] = (HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID);

Then the line

WaitForMultipleObjects (3, hThrds, TRUE, INFINITE);

will return an error since the other two thread handles are invalid.  If I put

WaitForMultipleObjects (1, hThrds, TRUE, INFINITE);

instead (because only one thread was created), this causes an error as well.  Therefore, how can I store the handles to a variable number of threads and then use WaitForMultipleObjects?  Or is there another solution that you might suggest?

FYI - I tried using calloc and malloc to create hThrds dynamically,

hThrds = calloc (3, sizeof (HANDLE));

but this did not work since HANDLE does not have a size.
0
jtrades
Asked:
jtrades
  • 3
  • 3
  • 2
  • +3
1 Solution
 
milindsmCommented:
Declare a class for thread object. It will have a linked list of thread handles. You may need to override [] operator. Also maintain the current thread count as a static member of that class. See if this works...!!!
0
 
niceprogrammerCommented:
do like this:


for(i = 0; i<3 ; i++)
{
WaitForMultipleObjects (i, hThrds, TRUE, INFINITE);  
}

Open in new window

0
 
jtradesAuthor Commented:
I was able to use the following line

HANDLE *hThrds = new HANDLE[numThreads];

where numThreads is declared at runtime.  It compiled and worked.  Does anyone see any problems with this method?
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
milindsmCommented:
But as you said, this number might vary.... right????
0
 
pgnatyukCommented:
I prefer to declare this array of handles as:
HANDLE arrHandles[MAX_POSSIBLE_NUMBER_OF_HANDLES];
but this array should contain only with the valid handles in the beginning and so, for WaitForMultipleObjects I pass the valid number of the objects to wait for.
For example the maximal number of handles can be 8, but now I need only 4, so the first 4 elements of this array are valid handles and 4 is the parameter for WaitForMultipleObjects.
0
 
evilrixSenior Software Engineer (Avast)Commented:
Why not just use a standard vector to solve your problem?
http://www.cplusplus.com/reference/stl/vector/

std::vector<HANDLE> vh;
vh.push_back((HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID));
... as many as you like
vh.push_back((HANDLE)_beginthreadex (NULL, 0, &ThreadFunction, &params, 0, &threadID));
WaitForMultipleObjects (vh.size(), &vh[0], TRUE, INFINITE);

Open in new window

0
 
Greg_ArnoldCommented:
Everyone, he's writing in C so suggeting classes and new() isn't going to work.  I tried

HANDLE *h = malloc(sizeof(HANDLE));

in VS 2005 and it worked for me.  Could you post what error you're getting when you try it?
0
 
pgnatyukCommented:
The error is simple - WaitForMultipleObjects does not wait.
So again, as the most people have said, in the beginning of the array of handles should be only valid handles; the first parameter for WaitForMultipleObject is the number of the valid handles in this array.
Add a stop event handle (a valid HANDLE created by CreateEvent) as the first array element. So even if one thread was created, you call WaitForMultipleObjects and everything works fine. In such cases you always may have few events - for example, pause and continue, stop, begin, etc.

0
 
pgnatyukCommented:
@Greg_Arnold: it is, probably, just a typo:
HANDLE *h = malloc(sizeof(HANDLE));
0
 
jtradesAuthor Commented:
Took Greg's suggestion with some modifications

HANDLE *h = (HANDLE *) calloc(thread_cnt, sizeof(HANDLE));

This seems to work fine.  Thanks for everyone's help.
0
 
jtradesAuthor Commented:
Just need to cast the pointer from calloc/malloc to the type you need.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

  • 3
  • 3
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now