CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Oct 2004
    Posts
    38

    when using multithread function - error

    It is happening something that I can not understand. When I run a function which injects 100 pulses (using external electronics...) from my main program it works properly but When I do the same using a function like (thread function):
    DWORD WINAPI ThreadClass::ThreadFunc(LPVOID pvParam)

    It goes crazy and injects less that what I expect. I have realized that it has something to do with time...because when I write Sleep(10) for example, it works better !!

    Anyone knows why it happens???

    Thanks,

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: when using multithread function - error

    This will be pretty hard to figure out without some sample code. Can you zip up the source and send it to us?

    Arjay

  3. #3
    Join Date
    Oct 2004
    Posts
    38

    Re: when using multithread function - error

    Ok, The program is very big then I will send part of it.

    The function with problem is (inside pulse_cpp):
    bool Sb_Actel::send_1000long_pulse(int node_id)
    which I programed to send actually 100 pulses but it is ok...

    I call this function from (case I D _ S C U R V E: ) from panel_of_function_cpp

    If I run the procedure which is comented it works properly. If I run like it is now (calling another thread) it does not work well...

    if you need something else tell me and I send more code...
    Attached Files Attached Files
    Last edited by rafraf; February 21st, 2005 at 02:01 PM.

  4. #4
    Join Date
    Oct 2004
    Posts
    38

    Re: when using multithread function - error

    I am new in multithread (I am using it for the first time) and I really believe that the error is something simpler that it seems...

    It could be that I am using a library that doesnt work well in a multithread process?? or I must use some libraries in order to get my program to work...??

    I am using on Code Generation: Debug Multithread

    and the function: CreateThread(...)

    I have also tried with _beginthread( Func, 0, (void *) (ch++)); but the error persists...

    any insight??

    thanks...
    Last edited by rafraf; February 22nd, 2005 at 09:18 AM.

  5. #5
    Join Date
    Oct 2004
    Posts
    38

    Re: when using multithread function - error

    That could be a problem with my class...

    When I get the routine inside the function I am calling (send_1000long_pulse) from the ThreadFunc and put it direct inside the ThreadFunc it works well...??

    I will send a peace of this class to see if someone finds something wrong...

    [QUOTE]

    ...
    using namespace std;

    class Sb_Actel
    {
    public:
    Sb_Actel(); //constructor
    ~Sb_Actel(); //destructor

    bool send_25ns_pulse(int node_id, int i2c_ch, BYTE DAC_value);
    bool send_long_pulse(int node_id);
    bool send_1000long_pulse(int node_id);
    bool send_40M_clk(int node_id);
    bool send_clk(int node_id, int i2c_ch, int counter_nr, int *value);
    bool select_swpulse_mode(int node_id);
    bool select_sw_start_stop_mode(int node_id);
    bool set_tmis_time_ms(int node_id, int time);
    bool write_ADDR_PULSE(int node_id);

    private:
    BYTE data[4];
    int index_actel;
    BYTE can_msg_cnf[4];
    };

    Sb_Actel::Sb_Actel() //constructor
    {
    //initialize variables
    index_actel = 0x4700;
    data[0] = 0;
    data[1] = 0;
    data[2] = 0;
    data[3] = 0;
    }
    Sb_Actel::~Sb_Actel() //destructor
    {
    }

    bool Sb_Actel::send_1000long_pulse(int node_id)
    {
    int i;

    data[0]=SW_PULSE;
    if(!COP_WriteSDO (CanInterface, node_id, 1, index_actel, ADDR_INT_PULSE_SEL, 1, data,can_msg_cnf)) return FALSE;

    data[0]=REG_PULSE;
    if(!COP_WriteSDO (CanInterface, node_id, 1, index_actel, ADDR_TEST_PULSE_SEL, 1, data,can_msg_cnf)) return FALSE;

    data[0]=0x0;
    if(!COP_WriteSDO (CanInterface, node_id, 1, index_actel, ADDR_PULSE, 1, data,can_msg_cnf)) return FALSE;

    for(i=0; i<=99;i++) //here is where I have the problem...
    {
    data[0]=0x1;
    if(!COP_WriteSDO (CanInterface, node_id, 1, index_actel, ADDR_PULSE, 1, data,can_msg_cnf)) return FALSE;
    data[0]=0x0;
    if(!COP_WriteSDO (CanInterface, node_id, 1, index_actel, ADDR_PULSE, 1, data,can_msg_cnf)) return FALSE;
    }

    return TRUE;
    }

    ...

    [QUOTE]
    Last edited by rafraf; February 22nd, 2005 at 09:41 AM.

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: when using multithread function - error

    Rafraf, are you accessing the a resource (library, data, etc.) from more than one thread? If you are, then you need to guard the access of a resource with a synchronization object such as a critical section.

    For example say I have a string resource that is accessed by two threads. If one thread is reading the string while the other thread is writing, there is going to be some data corruption (as the reading thread maybe getting some partially written data).

    Could this be what is happening?

    Btw, when you zip up your project, just zip the files up in their native format (*.h; *.cpp, etc.). That way, folks can load them up in the editor and get the benefit of getting color coded comments, formatting, etc. When saved as rtf files all this info is lost.

    Arjay

  7. #7
    Join Date
    Oct 2004
    Posts
    38

    Re: when using multithread function - error

    Yes, it could be...I am not using any protection but when I run this new thread I do not do nothing on the main thread, I just wait...(but pehaps it is not enough)

    now I send some files of the program in the right way!

    I will try to find out how to use synchronization object in my program, if you have any tutorial it would help.

    thanks!
    Attached Files Attached Files

  8. #8
    Join Date
    Oct 2004
    Posts
    38

    Re: when using multithread function - error

    I (I mean, you) have found the problem...I call the same routine from both threads...

    I have forgotten that I am constantly calling this function from the main thread in a pooling process...

    I will search for info about how to implement mutex and etc...

    Thanks!!

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: when using multithread function - error

    Rafraf, for sychronization within a process, you probably don't need to use a mutex but can use a critical section instead. I've attached a simple dialog application that uses two threads to fill and populate a list control with about 100,000 items. Items are created on one thread and pushed on to an STL vector. The second thread reads the items from the vector. Both threads lock the vector using a critical section. See the LVItemDataMgr.h for specifics.

    For ease of use, the critical section is contained in the following lightweight wrapper class:

    Code:
    class CLockableCS
    {
      // Methods
    public:
    	// Ctor / Dtor
    inline CLockableCS() throw() { InitializeCriticalSection( &m_CS ); }
    	inline ~CLockableCS() throw() { DeleteCriticalSection( &m_CS ); }
     
    	// Lock / Unlock
    inlinevoid Lock() throw() { EnterCriticalSection( &m_CS ); }
    	inlinevoid Unlock() throw() { LeaveCriticalSection( &m_CS ); }
     
      // Attributes
      private:
    	CRITICAL_SECTION m_CS; // Internal Critical Section
    };
    
    To guard a resource, you can declare an instance of CLockableCS directly (CLockableCS m_csDataStruct or derive a class from CLockableCS such as the following std::vector derived class:

    Code:
    // Turn a std::vector into a lockable vector (this class stores an array of CLVItemData pointers)
    class CLVItemDataList
      : public std::vector< CLVItemData* >, public CLockableCS
    {
      public:
      CLVItemDataList() {}
      ~CLVItemDataList() {}
    };
    
    Now to be really slick, we need a class that helps us perform the locking and automatic unlocking. Note: one the most common problems with regard to multithreaded programming is forgetting to release locks when they are no longer needed. IMO, a class such as this helps prevent these sorts of problems.

    Code:
    template<class T> class CAutoLockT
    {
      // Attributes
    private:
      T* m_pObject; // the locked object
     
      // Ctor/dtor
    public:
    	// Critical Section Ctor
    inline CAutoLockT( T* pObject ) throw() : m_pObject(pObject)
    	{
    	  ASSERT( NULL != pObject );
    	  m_pObject->Lock();
    	}
     
    // dtor
    inline ~CAutoLockT()
      {
    	m_pObject->Unlock();
      }
    };
    
    Next, let's put it all together with a class that uses a CLockableCS derived list and illustrates locking and unlocking:

    Code:
    class CLVItemDataMgr
    {
      public:
    
    
    CLVItemDataMgr() : m_lMaxCount( 1000000 ) { }
    
    ~CLVItemDataMgr() { }
    
    // Operations (public methods consumed by CLVSelStateDlg)
    
    public:
    
    // Cycle through the list and add each item into the list control
    // NOTE: This code is called from Thread 1
    HRESULT Populate( CListCtrl& ctlList )
    {
      HRESULT hr = S_OK;
      // Lock the list
    CAutoLockT< CLVItemDataList > lock( &m_LVItemDataList );
     
      // Cycle through the list and add each item into the list control
      for(CLVItemDataList::iterator it = m_LVItemDataList.begin();
    	it < m_LVItemDataList.end();
    	it++)
      {
    	CLVItemData* pLVItemData = (*it);
     
    	// Add this item to the list control.  NOTE: the actual code in the sample
    	// is different than below.  This code has been modified for clarity
    	pLVItemData->AddToListControl( ctlList );
      }
      return hr;
    }
    // Implementation
    
    private:
      // Method: RetrieveThread (Thread 2)
      // Purpose: Secondary Thread which adds Max Count items to the
      // LVItem Data list
      static UINT WINAPI RetrieveThread( LPVOID lpContext )
      {
    	CLVItemDataMgr* pLVItemDataMgr 
    	   = static_cast< CLVItemDataMgr* >( lpContext );
     
    	for( LONG lIndex = 0;
    	  lIndex < pLVItemDataMgr->GetMaxCount();
    	  lIndex++ )
    	{
    	   pLVItemDataMgr->InsertItem( lIndex );
    	}
    	return 0;
      }
     
      // Method: InsertItem
      // Purpose: Creates a new CLVItemData object and inserts it into the list
      HRESULT InsertItem( const UINT uIndex )
      {
    	HRESULT hr = S_OK;
    	CString sColumnOne = _T(""),
    	  sColumnTwo = _T("Col2"),
    	  sColumnThree = _T("Col3");
    
    	sColumnOne.Format( _T("Col1 : %d"), uIndex );
    	CLVItemData* pLVItemData = new CLVItemData( sColumnOne,
    	  sColumnTwo,
    	  sColumnThree );
    
    	if( NULL == pLVItemData )
    	{
    	  return E_OUTOFMEMORY;
    	}
    
    	try
    	{
    	  // Lock the list.  Prevent list access in thread 1
    	  CAutoLockT< CLVItemDataList > lock( &m_LVItemDataList );
    	  m_LVItemDataList.push_back( pLVItemData );
    	}  // CAutoLockT goes out of scope and automatically unlocks here
    	catch(std::bad_alloc)
    	{
    	  hr = E_OUTOFMEMORY;
    	}
    	return hr;
      }
     
      // Attributes
      private:
    	// The lockable vector.  This stl vector class holds pointers to 
    	// CLVItemData objects.
    	CLVItemDataList m_LVItemDataList;
     
    	LONG m_lMaxCount;
    };
    
    This sample was originally created to illustrate a virtual listview, so there is quite a bit of UI stuff in there. However the main threading and locking code is contained within the CLVItemDataMgr.h file so it shouldn't be too hard to filter out the threading related code.

    Arjay
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured