Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Thread Programming

Status
Not open for further replies.

AMosmann

Programmer
May 27, 2003
82
0
0
DE
Please don't send me to msdn, I tried this.
Maybe my English is too bad, but I did not find the answers I looked for.

I have a main thread, that starts a thread to read from file into an object, and another one, that displays the object, both of them should be killable from the main thread.

I know, a thread proc should be global and gets a thread structure with pointers to the datas, that shall be changed.

Questions:
Where do I put the synchronisation object, into tha object, into this structures, into the WindowObject, global anywhere else?

Who should destroy the thread structures for a thread, the thread itself, any other function?

How can I get to know, whether a thread had finished or is working? If CEvent is best, where to put this?

Maybe a Application has a possibility to start lots of threads, maybe readfile threads. If the user wishes to end all of them are to be killed before end the application.
Where are the sync objectes to be put, if I want to do this?

Thank you very much



Greetings Andreas
 
////////////client////////////////
#include<iostream>
#include<windows.h>

bool run = true;
DWORD WINAPI ThreadProc1(void* xx)
{

while(run)
{
cout << &quot;tread1&quot;<< endl;
}
run = false;
return 0;
}
DWORD WINAPI ThreadProc2(void* xx)
{
while(run)
{
cout << &quot;tread2&quot;<< endl;
}
run = false;
return 0;
}

int main()
{
DWORD th_id;
SomeClass params;
HANDLE hThread1 = CreateThread(0, 0, ThreadProc1, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}
HANDLE hThread1 = CreateThread(0, 0, ThreadProc2, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}

int i = 0;
while(i++)
{}
run = false;
return 0;
}
////////////client////////////////

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
Thanks Ion, and now to the questions:

let me say:


CData data;
// contains the data I want to use.

struct {
CData *data;
CAnyOtherData *other;
} CParam;

DWORD WINAPI ThreadProc1(void* xx)
{

while(run)
{
AVeryLongProcedureThatChangesEverything(xx->data);
}
run = false;
return 0;
}
DWORD WINAPI ThreadProc2(void* xx)
{
while(run)
{
AnotherVeryLongProcedureThatChangesEverything(xx->data);
//How to change, that every thread has correct data?
}
run = false;
return 0;
}

int main()
{
DWORD th_id;
CParam *params;

params=new CParam;
params->data=&data;

HANDLE hThread1 = CreateThread(0, 0, ThreadProc1, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}
params=new CParam;
params->data=&data;

HANDLE hThread1 = CreateThread(0, 0, ThreadProc2, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}

int i = 0;
while(i++)
{}
run = false;

//where to kill those params-blocks?
//where do I know from, that both threads finished, when I leave main?

return 0;
}


Greetings Andreas
 
you should just to create a new thread. You can create many threads with the same theradproc, but with different params. Each of them will be independent. Also you can make the threadproc a member of a class:
//a base class for any threads you create:
class CThreadBase
{
private:
static DWORD WINAPI ThreadProc1(CThreadBase* xx)
{
xx->run();
return 0;
}
public:
HANDLE start()
{
DWORD th_id;
return CreateThread(0, 0, ThreadProc2, (void*)this, 0, &th_id);

}
virtual void run() = 0;
};


//now using this class
class MyThread: CThreadBase
{
public:
void run()
{do_sometning}
};

int main()
{
....
MyThread x;
x.start();
MyThread y;
y.start();

There are many thigs also to learn about synchronization. Each thread could have an own message loop and you can send thread messages.


Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
Hi Ion...
>There are many thigs also to learn about synchronization.

That is it I want to know

To start a thread is easy, I use MFC, so CWinThread is ok.
To use a simple boolean to tell all threads to end is easy too.

but... after that there are the questions.

>Questions:
>Where do I put the synchronisation object, into tha object, into this structures, into the WindowObject, global anywhere else?

>Who should destroy the thread structures for a thread, the thread itself, any other function?

>How can I get to know, whether a thread had finished or is working? If CEvent is best, where to put this?

>Maybe a Application has a possibility to start lots of threads, maybe readfile threads. If the user wishes to end all of them are to be killed before end the application.
Where are the sync objectes to be put, if I want to do this?



Greetings Andreas
 
>Questions:
>Where do I put the synchronisation object, into tha object, into this structures, into the WindowObject, global anywhere else?
you should put synchronization methods just in the code you want to synchronize:
//
EnterCriticalSection( ..criticalsection..);
all code where will be synchronized on criticalsection
LeaveCriticalSection( ..criticalsection..);

>Who should destroy the thread structures for a thread, the thread itself, any other function?

Usualy thread should free structures. Many implementations uses reference count (AddRef/Release) to know if structures should be deleted.
>How can I get to know, whether a thread had finished or is working? If CEvent is best, where to put this?

>Maybe a Application has a possibility to start lots of threads, maybe readfile threads. If the user wishes to end all of them are to be killed before end the application.
To manipulate threads use:
ExitThread, CloseHandle, SuspendThread/ResumeThread, SetThreadPriority
To know if thread is finished, you should implement by yourself. To handle correctly threads sometimes is a little hard on win32.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
Thanky Ion, any further questions:


CData data{
CCriticalSection CriticalSectionElement;
}; // contains the data I want to use.

struct {
CData *data;
CAnyOtherData *other;
} CParam;

DWORD WINAPI ThreadProc1(void* xx)
{

while(run)
{
EnterCriticalSection( xx->data.CriticalSectionElement);
AVeryLongProcedureThatChangesEverything(xx->data);
LeaveCriticalSection( xx->data.CriticalSectionElement);
AnyCodeWithoutAccessToCriticalElements();
}
run = false;
return 0;
}

int main()
{
DWORD th_id;
CParam *params;

params=new CParam;
params->data=&data;

HANDLE hThread1 = CreateThread(0, 0, ThreadProc1, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}
params=new CParam;
params->data=&data;

HANDLE hThread1 = CreateThread(0, 0, ThreadProc2, (void*)&params, 0, &th_id);
if(!hThread1){COUT <<&quot;error on creating thread&quot;<< endl;;}

int i = 0;
while(i++)
{}
run = false;

return 0;
}


Is it like you told me?
>To know if thread is finished, you should implement by yourself.
Why not taking CEvent?

Thank you

Greetings Andreas
 
>> Where do I put the synchronisation object...

There is no &quot;cookbook&quot; design for thread synchronization. Each application has it’s own design criteria, requirements and goals. The multiple synchronization mechanisms and design patterns coupled with project uniqueness results in a multitude of design possibilities, some good… some not so good.

In order to be able to design synchronization you first must understand how all the available synchronization mechanisms work. This means doing research and studying the behavior until you have a clear understanding of them.

Ion’s thread class for thread creation is a great basis for thread creation. I highly recommend reading the technical articles on MSDN regarding the differences between and ramifications of the different thread creation mechanisms ( CreateThread, _beginthread, CWinThread) available to VC++ development.

&quot;But, that's just my opinion... I could be wrong.&quot;

-pete
 
>AMosmann
If you use MFC, CWinThread has methods InitInstance and ExitInstance what you can override. If you want to manipulate thread with events, just put a messageloop in each thread you want to manipulate with events.
while(GetMessage(&msg, 0, 0, 0))
{
switch(msg.message)
{
...
}
}

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
Minor suggestion:

For whatever synchronization mechanism you use, do try to encapsulate it in a class that you put locally on the stack for exception safety.

/Per
[sub]
if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
[/sub]
 

It sounds like this is what you're doing:

Receiving data and updating the dialogs from your receive thread if any dlgs are open using a pointer to each dlg. Only problem is you terminate the app and the receive thread terminates last and still trys to update a dlg that has been destroyed but it's pointer is not nulled so it asserts.

Here's what you should be doing:

The recieve thread queues the data as is comes in or stores it in a CDocument class. Each dlg has a timer, part of the CDialog class. Use this timer in each dialog to update thier dispaly say every 100mS buy reading the data in the queque or CDocument class. This way the dialog takes care of it's own updating.

It is more work at first but the good thing about doing it this way is you can create more views or dlgs and never need to mess with the recieve thread code again. Just add code for the updating of the new view or dlg. Your receive thread code is more portable too.

So main app:

OnStartUp()
- create queue
- create recieve thread (pass in pointer to queue to store data)
- create dlgs (pass in pointer to queue to read data)
- display dlgs

OnTerminateApp()
- destroy dlgs
- terminate thread
- close app


Brother C
 

Sorry about my previous reply. It was for another topic not this one.

On this topic now, you should defenetly be using CWinThread and AfxBeginThread( ) to start your threads for many reasons if your using VC++. MSDN library explains these reasons and answers all the questions you've asked here.

Cheers,

Brother C
 
>> you should defenetly be using CWinThread and AfxBeginThread( )

Perhaps you could explain your reasoning? Is it because AMosmann has stated he is using MFC objects in his threads. If so i would agree as long as he is not mixing C runtime library calls in that are thread related which he probably isn't.

Excerpt from
_beginthread performs some of the internal initialization for a new thread that other C runtime functions, such as signal, depend on. The rule is consistency: If your program manipulates threads with C runtime functions, then use only C runtime functions wherever you have a choice. If your program uses Win32 functions with its threads, then stick to CreateThread and ExitThread. Also, if the thread calls C runtime functions, then create it with the C functions rather than the Win32 API. A few C routines require the initialization that _beginthread performs.


There are other notable MSDN articles that should be read by first threading developers:




-pete
 
To check if a thread is running, use GetExitCodeThread(), ie:

Code:
bool thread_active(HANDLE thread)
{
 DWORD status;
 GetExitCodeThread(thread, &status);
 return status == STILL_ACTIVE;
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top