Click to See Complete Forum and Search --> : Multithreading: Creating Threads Within Threads?
tkrampe
September 28th, 2005, 03:49 PM
Hi, I'm a bit new to C# and I had a question about something that I can't figure out and can't seem to find any documentation on. In a program that I am writing I have a bit of code that contacts a server and builds up the folder structure of a given directory(i.e. sub directories, files, etc) and then returns it to the UI. I've designed it to be recursive so basically I have a method that is called from the UI and takes a folder path. It then creates an array of the items within the directory, and then goes through each item. If an item is found to be a directory it then calls the same method again passing it the new folder path so that its subitems can be sorted through. My code works fine, but it is pretty slow especially when you are dealing with a directory with many subdirectories, becuase it has to keep going to the server for information. So I decided to try a multithreaded approach. I want it so that every time this method is called a new thread is created. That way when a sub directory is found a new thread is created and the current thread just continues processing the folder it was currently working on. I was able to implement this and it too works, but I can't seem to figure out how to get my UI to pause till all these threads are done. I can get the UI to wait for the thread that it created to return, but since that thread also created its own worker threads the UI knows nothing about those. I've found many articles that use the thread pool to run several threads and then wait for them to finish, however I can't seem to figure out how to implement this since I'm creating new threads from within the thread that was originally called from the UI. Any help would be appreciated. Thanks.
Sorry for posting this in the Visual C++ area I'm new to the forum also and I guess I wasn't paying close enough attention. If a moderator wants to delete this I would appreciate it. Sorry.
kirants
September 29th, 2005, 04:21 PM
Try this:
Have a global counter
Have a global event which is initially reset.
Write a function to inc/dec it and wrapping it with Critical section.
Each thread will call inc first thing in it's thread procedure and dec last thing in it's thread procedure
the decrement function should do this. It should set a global event when the count goes to 0.
Your main app can wait on this event and when set knows there are no more threads.
However, this is not so foolproof in my opinion. There is a small window where in a thread has spawned a new thread, and has before exiting called dec count, but the new thread's thread proc hasn't started yet , so hasn't called inc count , and hence there is a false alarm of operation complete.
Anyways, I'll let you tweak it:
//global counter
DWORD g_dwThreadCount = 0;
//global event which is set when there are no threads running
HANDLE g_hOperationCompleted = NULL;
//critical section for inc/dec operation
CRITICAL_SECTION cs;
//in main program
g_hOperationCompleted = CreateEvent(NULL,TRUE,FALSE,NULL);
InitializeCriticalSection(&cs);
//launch first thread.
HANDLE hThread = CreateThread...( ThreadProc);
//let it run for a while so it gets a chance to inc count
Sleep(100);
//now start waiting
WaitForSingleObject(g_hOperationCompleted,INFINITE);
//inc/dec methods
void EnterThread()
{
EnterCriticalSection(&cs);
g_dwThreadCounter ++;
LeaveCriticalSection(&cs);
}
void LeaveThread()
{
EnterCriticalSection(&cs);
g_dwThreadCounter --;
//if count reached zero, trigger event
if(!g_dwThreadCounter)
SetEVent(g_hOperationCompleted);
LeaveCriticalSection(&cs);
}
//sample thread proc
UINT ThreadProc(LPVOID ..)
{
EnterThread();
//do stuff and optionally launch more threads with
//ThreadProc procedure.
LeaveThread();
}
Arjay
September 30th, 2005, 10:37 PM
Building on Kirants' work, you can also use the InterlockExchange family of functions. These could replace the critical section code:
For example:
//inc/dec methods
void EnterThread()
{
InterlockedIncrement( &g_lThreadCounter );
// EnterCriticalSection(&cs);
// g_dwThreadCounter ++;
// LeaveCriticalSection(&cs);
}
Of course the other functions would need to be modified as well.
Arjay
kirants
October 1st, 2005, 03:40 PM
good point , Arjay :thumb:
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.