Link to home
Start Free TrialLog in
Avatar of delicia071398
delicia071398

asked on

Problem with thread synchronization and multithread processing.

First a little background:
I am currently working on a program that waits for data from users via the internet.Currently , it immedialtely processes the information using a thread. I am adding a feature that allows the user to process the information at a time delay instead of immediatey. To do this I created a thread that simply sleeps for the length of the time delay, afterwhich the ProcessData thread is started. I used a critical section as a means of synchronizing the threads (this was necessary because if they were not synchronized I got a C++ runtime error).

The problem that I am having now is that the process waits to deal with the data that is being sent by the user until after the delay from a previous user has been completed. I am currently using WaitForMultipleObjects which  is leading to the problem. Using WaitForSingleObject(DelayThread,INFINITE) and this leads to the same  problem. If I don't have a wait at all I get a C++ runtime error.

Here is my question:
How can I have the program process infromation from one source at a delay and still have it process information from another source that is not at a delay WITHOUT the second set of information having to wait until after the delay thread has been completed for the first set of infromation?

I hope this makes sense.
Avatar of nietod
nietod

>> How can I have the program process infromation from one source at a
>> delay and still have it process information from another source that is
>> not at a delay WITHOUT the second set of information having to
>> wait until after the delay thread has been completed for the first set of
>> infromation?

It is not clear why this problem is occuring.  Why do you think you have to wait?  

Is it that the sleeping (waiting) thread is supposed to handle both sets of data, and is sleeping for one so it doesn't "see" the one that it doesn't need to sleep for?

Is it that there is one set of data (not two) and both forms of processing must occur in the one set?

Or is there something else?


Avatar of delicia071398

ASKER

If I do not have a WaitForXXXObject(s) I get a C++ runtime error that I have traced back to the call to DelayThread.Which at that time would sleep for the delay time and then call another function the started the ProcessDataThread.

I then redesigned the program so that the the first thread (Thread1) would sleep (and that is it) without calling the function that starts ProcessDataThread(Thread2).Thread2 is supposed to handle both sets of data but Thread1 is not. I use a series of if statements that determine whether or not the data is to be delayed if it is not the _beginthread(Thread1) is bypassed.

As a  sidebar the design for the program is such that each piece if data submited by the user is to be delayed (if necessary) otherwise be processed immediately.There are at any given time any number of users that can be sending data to the program via an application extention (dll) that receives information from the internet.This data may/may not have a time delay. The time delay from one set of data sent to the prgram from the Dll should not affect the processing of another set of data that is sent to the program from that same Dll. The program is designed to run "infinitely" and continually waits for messages from the internet.
The design you describe requires a separate thread for each pice of data which requires a delay. The basic plan would be:

- thread1 is in a loop looking for messages

- if a message comes in which is to be processed immediately, thread1 processes it

- if a message comes in which needs to be delayed, thread1 creates a new thread threadN (where N gets larger as there are simultaneous requests which need delays)

- each threadN sleeps the required time, then wakes up and processes the data itself (without calling thread1). When done, each threadN terminates itself.

The reason this is necessary is if the basic delay mechanism is for a thread to sleep, then either each new piece of data needs its own thread or else it has to wait for the previous delay to be complete so the shared thread is again available. There's no other way.

Having said all that, that's the easiest way to modify your present design to make it work, but it's probably not how I'd do it. Creating a new thread all the time has significant overhead, and you have to be careful to lock common resources with Critical Sections. (One critical section protecting all your data processing sounds feasible, though, since all threads do the same thing).

The other way to do it, and to remain a single-threaded app with all the simplicity that brings, is to maintain your own list of pieces of data awaiting processing. This scenario would work as follows:

- thread is in a loop looking for messages

- if a message comes in which is to be processed immediately, thread processes it

- if a message comes in which needs to be delayed, thread adds it to an array of pending messages along with the current time (obtained from GetTickCount).

- before going back into its message loop, thread always looks into the array to see if any entries are ready to run. This is done by calling GetTickCount to get the current time and seeing which if any of the array entries' time delays have passed. Those who are ready are processed and removed from the array.

- If there are entries in the array, before we go back looking for new messages we need to start a timer, with the time set to the delay for the next array entry which should run. Only one timer is ever used, though - if we already started the timer but haven't received notification yet then no need to do anything here. The timer doesn't actually directly time the delays, it is there to wake up the thread so it can check its array.

Let me know if you need clarification... if what I said helps I'll repost it as an answer. Good luck!
Hello Delicia!
I suggest that you establish two queues for the information processing. One queue would be the delay queue, the other would be the immediate queue.
Data entered into the delay queue is associated with a time stamp.
Both queues should be monitored for explosion prevention (for example, requests are not admitted for length of queue exceeding 20).
The thread polls both queues. If the immediate queue is non empty, all requests need to be processed.
The Delay queue is monitored, and using the time stamp, requests are served "when ripe".
Note, that this mechanism also allows you to balance both queues with the introduction of queue balancing policy: For example, no more than x immediate requests are served before the delay queue is polled; Delayed requests that have not been served when due may be entered in front of the immediate queue.
Good luck, Roni
Alamo,

Your answer to the question was great. I used the array to store the messages and that alleviated the problem without having to deal with the overhead of continually creating new threads.

I need clarification on the use of GetTick Count though I have never used it before. Am I correct in saying that the count is represented in milliseconds? and is returned as a DWORD? Also how would I know which message is to be sent next . Would I have to loop through the array to find the next message to go that i snot one of the messages whose delay has expired?
ASKER CERTIFIED SOLUTION
Avatar of alamo
alamo

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