Click to See Complete Forum and Search --> : Help with multithreaded programming


LarryChen
July 5th, 2005, 02:00 PM
I created two threads-- thread1 is for writing to a file and thread2 is for reading from the same file, in the main thread. Writing to a file may take a while so during the writing, I wish to read the file in the mean time(well in some sense). My problem is that which thread that is going to be executed is random. So it messed up, for example, reading a file before anything is written to a file. How can I ensure that thread1 is going to be executed first, then switch to thread2, then switch to thread1, etc. Please give me some clues!

cilu
July 5th, 2005, 02:08 PM
Take a look at WaitForSingleObject.

drewdaman
July 5th, 2005, 02:09 PM
you will have to have some sort of variable accessible by both threads so you know how far you can read... or at least i ca't think of a better way!

i guess you are not looking for things like events, critical sections, semaphores.. not too clear on exactly what you're doing... but in case you don't already know how to use these, take a look and see if they help! the waitforsingleobject() thing cilu mentioned waits for these things...

Andreas Masur
July 5th, 2005, 03:40 PM
[ Redirected thread ]

Andreas Masur
July 5th, 2005, 03:41 PM
Synchronization (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/synchronization.asp)

LarryChen
July 5th, 2005, 04:40 PM
Thanks for your suggestions. Actually, I tried to use Waitforsingleobject on one thread. But once it is returned from Waitforsingleobject, the waited thread will never have a chance to be executed again.I expect thread1 to be executed FIRST, then the program can swith between thread1 and thread2(reading and writing). I don't expect thead2 be executed after thread1 is completely done. Any ideas how to do that? Thank you very much!
you will have to have some sort of variable accessible by both threads so you know how far you can read... or at least i ca't think of a better way!

i guess you are not looking for things like events, critical sections, semaphores.. not too clear on exactly what you're doing... but in case you don't already know how to use these, take a look and see if they help! the waitforsingleobject() thing cilu mentioned waits for these things...

drewdaman
July 5th, 2005, 04:51 PM
larry, i think you should post some code so we can take a look at what you're doing.. things are much clearer that way and its usually much quicker to fix the problem.

LarryChen
July 5th, 2005, 05:10 PM
Okey, I attach my code this time. If you have any questions with my code, please let me know. Thank you very much!
larry, i think you should post some code so we can take a look at what you're doing.. things are much clearer that way and its usually much quicker to fix the problem.

Andreas Masur
July 5th, 2005, 05:13 PM
Thanks for your suggestions. Actually, I tried to use Waitforsingleobject on one thread. But once it is returned from Waitforsingleobject, the waited thread will never have a chance to be executed again.I expect thread1 to be executed FIRST, then the program can swith between thread1 and thread2(reading and writing). I don't expect thead2 be executed after thread1 is completely done. Any ideas how to do that? Thank you very much!
Well...I am not sure whether I understand the above...but I would use two events which would be set in an alternating way...

// Pseudo code
Event one
Event two

Thread One
{
while(true)
{
// Wait for Event one
// Reset Event one
// Do the stuff
// Set Event two
}
}

Thread Two
{
while(true)
{
// Wait for Event two
// Reset Event two
// Do the stuff
// Set Event one
}
}

Andreas Masur
July 5th, 2005, 05:19 PM
Okey, I attach my code this time. If you have any questions with my code, please let me know. Thank you very much!
Two obvious points (didn't look that closely)...

You are using critical sections which are being used to synchronize access to shared data but not execution of threads
These critical section are local to the function which means they are different objects. In order to syncronize, you would need to make the same object available to all the threads.
You don't want to add the whole MFC just because of any synchronization class...

How should these threads be synchronized? In other words, when should what thread execute?

LarryChen
July 5th, 2005, 05:36 PM
Thanks for your suggestions! You are right, I will declare critical section as a global object. But at this point, I am looking for some means to switch between two threads execution.
Two obvious points (didn't look that closely)...

You are using critical sections which are being used to synchronize access to shared data but not execution of threads
These critical section are local to the function which means they are different objects. In order to syncronize, you would need to make the same object available to all the threads.
You don't want to add the whole MFC just because of any synchronization class...

How should these threads be synchronized? In other words, when should what thread execute?

Andreas Masur
July 6th, 2005, 01:57 AM
Thanks for your suggestions! You are right, I will declare critical section as a global object. But at this point, I am looking for some means to switch between two threads execution.
You didn't answer my questions...

How should these threads be synchronized? In other words, when should what thread execute?

pranavsharma
July 7th, 2005, 09:34 AM
You can use Crtical Sections but they will be some complicated . For easier implementation you can use Global flag variable for the same to provide the sync.

Arjay
July 7th, 2005, 12:35 PM
Thanks for your suggestions. Actually, I tried to use Waitforsingleobject on one thread. But once it is returned from Waitforsingleobject, the waited thread will never have a chance to be executed again.I expect thread1 to be executed FIRST, then the program can swith between thread1 and thread2(reading and writing). I don't expect thead2 be executed after thread1 is completely done. Any ideas how to do that? Thank you very much!I've waited a bit to chime in here, just to see of there could be a clarification of what you are looking for.

At any rate, it seems you need to have each thread alternate - that is, one thread writes for a bit and then the other thread reads and so on. Correct? If this is true, then you aren't going to derive any benefit from using two threads.

Why? One of the main benefits of threading is to allow continuous processing of work. Consider a single threaded word processor print operation. In a single threaded app when the user prints, the user can't type until the printing has completed. In a multithreaded app, the user can continue to type while the printing is occuring because a second thread is performing the printing in parallel [with the typing thread] - in other words the threads are operating asynchronously.

What you are describing - one thread writes for a while and then the second thread gets to read is really a synchronous operation so you may be better off doing this in one thread.

On the other hand, depending on more details required for you design you may not.

So let's look at doing it with two threads. Just create the two threads (T1 & T2) and use two events (E1 & E2) to synchronize the threads. T1 will represent the writing thread and T2 will be the reading thread.

Internally in a loop, each thread waits on the 'opposite' event (T1 waits on E2 and T2 waits on E1). You'll first create both events and threads and initially set the E2 event which causes T1 to execute. You'll let T1 execute for a while and then call SetEvent on E1. T1 is at the end of its loop and goes back to waiting on E2. Since E1 has been set, T2 wakes up and starts reading, when you've decided that it's finished reading, you'll set E2 (so T1 can wake up) and so on.

Something that I haven't mentioned is that you probably need to track the current read and write positions of the file. These variables will need to be protected which can be easily done with the InterlockExhange family of functions.

Arjay

LarryChen
July 7th, 2005, 11:31 PM
Thanks so much for your useful comments. I have modified my code but it still didn't work. I already attach the modified code with this post. There is two major problems. First of all, the program is in a dead loop at the end. Secondly, after writing thread is executed first, if you debug the program, you will find a string is indeed written into the file by checking int n = fwrite((void*)s,sizeof(char),count,output). Then when reading thread is executed, fgets(buffer,128,output) always returns NULL meaning that nothing has been written into output. That is very strange. Please help me with the problems! Thank you very much!
I've waited a bit to chime in here, just to see of there could be a clarification of what you are looking for.

At any rate, it seems you need to have each thread alternate - that is, one thread writes for a bit and then the other thread reads and so on. Correct? If this is true, then you aren't going to derive any benefit from using two threads.

Why? One of the main benefits of threading is to allow continuous processing of work. Consider a single threaded word processor print operation. In a single threaded app when the user prints, the user can't type until the printing has completed. In a multithreaded app, the user can continue to type while the printing is occuring because a second thread is performing the printing in parallel [with the typing thread] - in other words the threads are operating asynchronously.

What you are describing - one thread writes for a while and then the second thread gets to read is really a synchronous operation so you may be better off doing this in one thread.

On the other hand, depending on more details required for you design you may not.

So let's look at doing it with two threads. Just create the two threads (T1 & T2) and use two events (E1 & E2) to synchronize the threads. T1 will represent the writing thread and T2 will be the reading thread.

Internally in a loop, each thread waits on the 'opposite' event (T1 waits on E2 and T2 waits on E1). You'll first create both events and threads and initially set the E2 event which causes T1 to execute. You'll let T1 execute for a while and then call SetEvent on E1. T1 is at the end of its loop and goes back to waiting on E2. Since E1 has been set, T2 wakes up and starts reading, when you've decided that it's finished reading, you'll set E2 (so T1 can wake up) and so on.

Something that I haven't mentioned is that you probably need to track the current read and write positions of the file. These variables will need to be protected which can be easily done with the InterlockExhange family of functions.

Arjay

Arjay
July 8th, 2005, 03:10 PM
Larry, you need to pass the event handles to each of your thread procedures. Plus you need to wait for the events in each thread proc, and set each event so the opposite thread wakes up appropriately.

I've attached a sample app, which simulates the reading and writing to a file. Although it doesn't actually perform any file reading or writing, it does keep track of a file read/write positions. So it should be somewhat simple to convert to real file operations.

Be warned that this code has been written in more of a C++ style where the thread procs are static members of a class. I chose this method because it makes things much easier to pass data around between threads.

Anyway, here's the output:

Starting up Reader thread...
Starting up Writer thread...
Operation File Pos
Writing... 256
Reading... 0
Writing... 512
Reading... 256
Writing... 768
Reading... 512
Writing... 1024
Reading... 768
Writing... 1280
Reading... 1024
Writing... 1536
Reading... 1280
Writing... 1792
Reading... 1536
Writing... 2048
Reading... 1792
Writing... 2304
Reading... 2048
Writing... 2560
Reading... 2304
Writing... 2816
Reading... 2560
Writing... 3072
Reading... 2816
Writing... 3328
Reading... 3072
Writing... 3584
Reading... 3328
Writing... 3840
Reading... 3584
Writing... 4096
Reading... 3840
Writing... 4352
Reading... 4096
Writing... 4608
Reading... 4352
Writing... 4864
Reading... 4608
Writing... 5120
Reading... 4864
Writing... 5376
Reading... 5120
Writing... 5632
Reading... 5376
Writing... 5888
Reading... 5632
Writing... 6144
Reading... 5888
Writing... 6400
Reading... 6144
Writing completed - shutting down...
Reader thread exiting...
Writer thread exiting...

Press any key to continue


Arjay

P.S. I wrote this in VC7.1 so if you are using an earlier compiler just copy the code out of AltThreads.cpp.

LarryChen
July 12th, 2005, 06:36 PM
Thanks so much for your sample code. I tried to use your methology in my code but still it didn't work. It looked like the reading thread is always stucked, which means the writing thread is not able to reset reading event and so the reading thread is always blocked. I have attached my code. Please help me! I am a multithreading newbie!
Larry, you need to pass the event handles to each of your thread procedures. Plus you need to wait for the events in each thread proc, and set each event so the opposite thread wakes up appropriately.

I've attached a sample app, which simulates the reading and writing to a file. Although it doesn't actually perform any file reading or writing, it does keep track of a file read/write positions. So it should be somewhat simple to convert to real file operations.

Be warned that this code has been written in more of a C++ style where the thread procs are static members of a class. I chose this method because it makes things much easier to pass data around between threads.

Anyway, here's the output:

Starting up Reader thread...
Starting up Writer thread...
Operation File Pos
Writing... 256
Reading... 0
Writing... 512
Reading... 256
Writing... 768
Reading... 512
Writing... 1024
Reading... 768
Writing... 1280
Reading... 1024
Writing... 1536
Reading... 1280
Writing... 1792
Reading... 1536
Writing... 2048
Reading... 1792
Writing... 2304
Reading... 2048
Writing... 2560
Reading... 2304
Writing... 2816
Reading... 2560
Writing... 3072
Reading... 2816
Writing... 3328
Reading... 3072
Writing... 3584
Reading... 3328
Writing... 3840
Reading... 3584
Writing... 4096
Reading... 3840
Writing... 4352
Reading... 4096
Writing... 4608
Reading... 4352
Writing... 4864
Reading... 4608
Writing... 5120
Reading... 4864
Writing... 5376
Reading... 5120
Writing... 5632
Reading... 5376
Writing... 5888
Reading... 5632
Writing... 6144
Reading... 5888
Writing... 6400
Reading... 6144
Writing completed - shutting down...
Reader thread exiting...
Writer thread exiting...

Press any key to continue


Arjay

P.S. I wrote this in VC7.1 so if you are using an earlier compiler just copy the code out of AltThreads.cpp.

Arjay
July 12th, 2005, 07:13 PM
Thanks so much for your sample code. I tried to use your methology in my code but still it didn't work. It looked like the reading thread is always stucked, which means the writing thread is not able to reset reading event and so the reading thread is always blocked. I have attached my code. Please help me! I am a multithreading newbie!While it seems that you are writing in small chunks, it doesn't look like you are reading in small chunks.

Are you sure this code only reads for a certain number of bytes before allowing T1 to run? It seems that it always reads to the end of the file. Is this what you want?

Arjay
while(readcount<writecount && fgets(buffer,128,output)!=NULL)

{

retrievedata(&buffer);

strcat(buffer,"\n");

printf(buffer);

readcount++;

}

SetEvent(hEvent1);

LarryChen
July 12th, 2005, 07:31 PM
Thanks for your reply! The function fgets reads characters from the current stream position to and including the first newline character. So it always reads one line every time. Is anything wrong?
While it seems that you are writing in small chunks, it doesn't look like you are reading in small chunks.

Are you sure this code only reads for a certain number of bytes before allowing T1 to run? It seems that it always reads to the end of the file. Is this what you want?

Arjay
while(readcount<writecount && fgets(buffer,128,output)!=NULL)

{

retrievedata(&buffer);

strcat(buffer,"\n");

printf(buffer);

readcount++;

}

SetEvent(hEvent1);