Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Returning a value from a Worker Thread

Returning a value from a Worker Thread

Scheduled Pinned Locked Moved C / C++ / MFC
graphicsdebuggingquestion
6 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Steve Messer
    wrote on last edited by
    #1

    I have a function that recursively counts the number of files of a given type from the specified path. It works as desired when used as a regualar function but I am trying to use this function in a worker thread that would return the number of files counted. I have tried everything that I can think of but the results is always zero. Here is the struct that I pass as a param to the threadproc

    struct THREADSTRUCT
    {
        CString filename;
        int count;
    } ;
    

    Here is my calling function.

    int CPlayer::CountFiles( string path )
    {
        _paramCount->filename = path.c_str();
        _paramCount->count = 0;
        AfxBeginThread( Count, _paramCount );
       
        return _paramCount->count; // this is one of many attempts
    }
    

    Here is my threadproc

    UINT Count( LPVOID pParam ) 
    {
    	THREADSTRUCT*    ts = (THREADSTRUCT*)pParam;
    	assert( !ts->filename.IsEmpty() );
    	int count = 0;
     		
    	vector< string > files;
    	vector< string > dirs;
    
    	string path = ts->filename.GetBuffer();
    
    	string types[] = 
    	{
    	  ".mp3",".mp2",".mp1",".ogg",".flac",".flc",".mpc",".ape",".ofr",".mpa",".wma"
    	};
    
    	int size = dim(types);
    
    	if( *(path.end() - 1) != '\\' && *(path.end() - 1) != '/' )
    		path += '\\';
    	
    	string spec( path + "*.*" );
    
    	_finddata_t fd;
    	int handle = (int)_findfirst( spec.c_str(), &fd );
    	if( handle == -1 )
    	    return 0;
    	do
    	{
    		if( fd.attrib & _A_SUBDIR )
    		{
    		    if( fd.name != string(".") && fd.name != string("..") )
    			dirs.push_back( path + fd.name );
    		}
    		else
    		{
    		    if( find_if( types, types+size, is_ext( fd.name ) ) != types+size )
    		    {
    			files.push_back( path + fd.name );
    			count++;
    			ts->count++;
    			ct++;
    			pCPlayer->_paramCount->count++;
    			//TRACE( "TS COUNT : %d", ts->count); TRACE("\n");
    		    }
    		}
    	}while( !_findnext( handle, &fd ) );
    	_findclose(handle );
    
    	for( size_t i=0; i_paramCount->filename = dirs[i].c_str(); 
                count += (int)Count( pCPlayer->_paramCount ); 		
    	}
    
    	return count;  
    }
    

    I have tried global variables and nothing seems to work. What am I missing?

    D 1 Reply Last reply
    0
    • S Steve Messer

      I have a function that recursively counts the number of files of a given type from the specified path. It works as desired when used as a regualar function but I am trying to use this function in a worker thread that would return the number of files counted. I have tried everything that I can think of but the results is always zero. Here is the struct that I pass as a param to the threadproc

      struct THREADSTRUCT
      {
          CString filename;
          int count;
      } ;
      

      Here is my calling function.

      int CPlayer::CountFiles( string path )
      {
          _paramCount->filename = path.c_str();
          _paramCount->count = 0;
          AfxBeginThread( Count, _paramCount );
         
          return _paramCount->count; // this is one of many attempts
      }
      

      Here is my threadproc

      UINT Count( LPVOID pParam ) 
      {
      	THREADSTRUCT*    ts = (THREADSTRUCT*)pParam;
      	assert( !ts->filename.IsEmpty() );
      	int count = 0;
       		
      	vector< string > files;
      	vector< string > dirs;
      
      	string path = ts->filename.GetBuffer();
      
      	string types[] = 
      	{
      	  ".mp3",".mp2",".mp1",".ogg",".flac",".flc",".mpc",".ape",".ofr",".mpa",".wma"
      	};
      
      	int size = dim(types);
      
      	if( *(path.end() - 1) != '\\' && *(path.end() - 1) != '/' )
      		path += '\\';
      	
      	string spec( path + "*.*" );
      
      	_finddata_t fd;
      	int handle = (int)_findfirst( spec.c_str(), &fd );
      	if( handle == -1 )
      	    return 0;
      	do
      	{
      		if( fd.attrib & _A_SUBDIR )
      		{
      		    if( fd.name != string(".") && fd.name != string("..") )
      			dirs.push_back( path + fd.name );
      		}
      		else
      		{
      		    if( find_if( types, types+size, is_ext( fd.name ) ) != types+size )
      		    {
      			files.push_back( path + fd.name );
      			count++;
      			ts->count++;
      			ct++;
      			pCPlayer->_paramCount->count++;
      			//TRACE( "TS COUNT : %d", ts->count); TRACE("\n");
      		    }
      		}
      	}while( !_findnext( handle, &fd ) );
      	_findclose(handle );
      
      	for( size_t i=0; i_paramCount->filename = dirs[i].c_str(); 
                  count += (int)Count( pCPlayer->_paramCount ); 		
      	}
      
      	return count;  
      }
      

      I have tried global variables and nothing seems to work. What am I missing?

      D Offline
      D Offline
      DavidR_r
      wrote on last edited by
      #2

      Your problem is that the main thread ends its work before the working thread gets a chance to do anything. it even does not has time for the context switch. You should use events. Check the WaitForSingleObject(), CreateEvent() and SetEvent() functions in MSDN. Generally you should wait for the event in the main thread and send it from the working thread when it's finished. Good luck DavidR

      S 1 Reply Last reply
      0
      • D DavidR_r

        Your problem is that the main thread ends its work before the working thread gets a chance to do anything. it even does not has time for the context switch. You should use events. Check the WaitForSingleObject(), CreateEvent() and SetEvent() functions in MSDN. Generally you should wait for the event in the main thread and send it from the working thread when it's finished. Good luck DavidR

        S Offline
        S Offline
        Steve Messer
        wrote on last edited by
        #3

        What do you mean my main thread is ending before the worker thread does anything? I am starting the worker thread in OninitDialog() so the main thread is not ending. Thanks for the direction, I will give those functions a whirl.

        T 1 Reply Last reply
        0
        • S Steve Messer

          What do you mean my main thread is ending before the worker thread does anything? I am starting the worker thread in OninitDialog() so the main thread is not ending. Thanks for the direction, I will give those functions a whirl.

          T Offline
          T Offline
          Tom Archer
          wrote on last edited by
          #4

          The start of the thread is asynchronous. IOW, you specify to start the thread and pass a fcn pointer and the call returns immediately. In the background the thread is started. Therefore, you have to decide how you want your thread to communicate back to the caller. David was referring to using events as the thread synchronization mechanism. You can find many samples and articles on doing that. Here's one I quickly grabbed from google: http://www.codersource.net/win32_waitforsingleobject.html[^] I'm sure there are several on this site as well. If you're starting the thread from the dialog's init function, you obviously don't want to hold up that function from completing. There are several ways around this. One very easy way would be to start a timer in the dialog's OnInitDialog function where the timer function could then start the thread as per David's (and the article's) instruction.

          S 1 Reply Last reply
          0
          • T Tom Archer

            The start of the thread is asynchronous. IOW, you specify to start the thread and pass a fcn pointer and the call returns immediately. In the background the thread is started. Therefore, you have to decide how you want your thread to communicate back to the caller. David was referring to using events as the thread synchronization mechanism. You can find many samples and articles on doing that. Here's one I quickly grabbed from google: http://www.codersource.net/win32_waitforsingleobject.html[^] I'm sure there are several on this site as well. If you're starting the thread from the dialog's init function, you obviously don't want to hold up that function from completing. There are several ways around this. One very easy way would be to start a timer in the dialog's OnInitDialog function where the timer function could then start the thread as per David's (and the article's) instruction.

            S Offline
            S Offline
            Steve Messer
            wrote on last edited by
            #5

            Okay so answer a dumb question. Obviously I don't understand so bare with me. How will setting things up like you say effect wheither or not my function returns a value. Thanks.

            T 1 Reply Last reply
            0
            • S Steve Messer

              Okay so answer a dumb question. Obviously I don't understand so bare with me. How will setting things up like you say effect wheither or not my function returns a value. Thanks.

              T Offline
              T Offline
              Tom Archer
              wrote on last edited by
              #6

              There are a couple of ways to do this: For example... * You could have a class (CMyWorkerThread) * CMyWorkerThread could also have a static member function that acts as the thread function (CMyWorkerThread::DoWork) * Your client code constructs a CMyWorkerThread object and creates a thread passing the CMyWorkerThread member function pointer * Your client code then blocks on an event that signifies that the thread has finished (e.g., by calling WaitForSingleObject) * CMyWorkerThread::DoWork processes the work and when done it sets a member variable that represents the return value. * CMyWorkerThread::DoWork then clears the event * Once the CMyWorkerThread::DoWork sets the event, the client's call to WaitForSingleObject completes and the client can then access the CMyWorkerThread object's return value member variable Another way... * You could have a class (CMyWorkerThread) * CMyWorkerThread has a constructor that takes a callback function that is stored as a member variable * CMyWorkerThread has a static member function that acts as the thread function (CMyWorkerThread::DoWork) * Your client code constructs a CMyWorkerThread object (passing the callback) and creates a thread passing the CMyWorkerThread member function pointer * CMyWorkerThread::DoWork processes the work and when done it calls the callback function to notify the client that the work is completed and the return code

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups