CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Dec 2021
    Posts
    3

    Notify Me When Data is Received on Serial Port Without Blocking Other Events?

    Hi All,

    I have a Visual C++ application that is designed to listen on a serial port for polls received from a remote location and then generate responses based on data the user enters from the GUI. In the original implementation, once the user clicks on a button in the main GUI the following loop is started:

    Code:
    void CInteractDlg::ListenForOffice()
    {
    	//This function listens for messages on the serial port
    	//and captures them in an array for evaluation.
    	BOOL b_response_received;
    	Status = ReadFile(hComm, ReadData, sizeof(ReadData), &NoBytesRead, NULL);
    	if (NoBytesRead > 0)
    	{
    		b_response_received = true;
    		int local_loop = 0;
    		while (local_loop < NoBytesRead)
    		{
    			m_pInData[local_loop] = ReadData[local_loop];
    			++local_loop;
    			//m_pInData now holds the received message.
    
    		}
    		//We need to process it next to ensure it is valid
    		InteractDlg::ProcessOfficeMessage();
    	}
    	//Finally, after we've processed whatever we need to do and send a
    	//response, we go back to listening
    	CInteractDlg::ListenForOffice();
    }
    While this code does generate the proper responses to the polls from the office, it "blocks" the recognition of any user interaction with things like buttons on the main GUI. There's no time for them to be recognized because this loop is constantly occurring. There are polls received on the serial port within a fraction of a second after sending something, so there's constantly things being received on the serial port.

    What I need is for something (almost in the background?) to constantly be looking at the serial port and effectively flagging me when there's something there so I can respond, but otherwise, the user should still me about to manipulate the controls on the GUI and those events get recognized by the application (as this interaction changes how the application responds to polls from the office when the function ProcessOfficeMessage() is called.

    The serial port handle was created as follows:

    Code:
    hComm = CreateFile(m_commport, //friendly name
    			GENERIC_READ | GENERIC_WRITE,      // Read/Write Access
    			0,                                 // No Sharing, ports cant be shared
    			NULL,                              // No Security
    			OPEN_EXISTING,                     // Open existing port only
    			0,                                 			
    			NULL);
    Any help would be greatly appreciated. This is driving me crazy.

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: Notify Me When Data is Received on Serial Port Without Blocking Other Events?

    Two important things you have to consider:
    1. To prevent your UI from blocking you have put all serial port operations in the secondary thread(s).
    2. To allow "simultaneous" read/write from/to serial port you must use overlapped I/O.

    There is a great Joe Newcomer's essay Serial Port I/O with a code samples. It does work very good (I used it, with some light changes/extensions, for more than a decade)

    Alternatively you could also look at the PJ Naughter samples here: http://www.naughter.com/serialport.html
    Victor Nijegorodov

  3. #3
    Join Date
    Dec 2021
    Posts
    3

    Re: Notify Me When Data is Received on Serial Port Without Blocking Other Events?

    Thanks Victor. With respect to this:

    Quote Originally Posted by VictorN View Post
    Two important things you have to consider:
    1. To prevent your UI from blocking you have put all serial port operations in the secondary thread(s).
    The problem I'm having is that once ListenForOffice gets called, the application never can be notified when the user does something like click on a button. So is this what you're saying:

    Code:
    void CInteractDlg::ListenForOffice()
    {
    //Main loop to run 
    	CInteractDlg::ReadFromPort();
    //Other code to run
    	CInteractDlg::ListenForOffice();
    }
    
    void CInteractDlg::ReadFromPort()
    {
    	//This function listens for messages on the serial port
    	//and captures them in an array for evaluation.
    	BOOL b_response_received;
    	Status = ReadFile(hComm, ReadData, sizeof(ReadData), &NoBytesRead, NULL);
    	if (NoBytesRead > 0)
    	{
    		b_response_received = true;
    		int local_loop = 0;
    		while (local_loop < NoBytesRead)
    		{
    			m_pInData[local_loop] = ReadData[local_loop];
    			++local_loop;
    			//m_pInData now holds the received message.
    
    		}
    		//We need to process it next to ensure it is valid
    		InteractDlg::ProcessOfficeMessage();
    	}
    	//Finally, after we've processed whatever we need to do and send a
    	//response, we go back to listening
    }

  4. #4
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: Notify Me When Data is Received on Serial Port Without Blocking Other Events?

    Quote Originally Posted by Electroskill776 View Post
    ...
    The problem I'm having is that once ListenForOffice gets called, the application never can be notified when the user does something like click on a button. So is this what you're saying:

    Code:
    void CInteractDlg::ListenForOffice()
    {
    //Main loop to run 
    	CInteractDlg::ReadFromPort();
    //Other code to run
    	CInteractDlg::ListenForOffice();
    }
    
    void CInteractDlg::ReadFromPort()
    {
    	//This function listens for messages on the serial port
    	//and captures them in an array for evaluation.
    	BOOL b_response_received;
    	Status = ReadFile(hComm, ReadData, sizeof(ReadData), &NoBytesRead, NULL);
    	if (NoBytesRead > 0)
    	{
    		b_response_received = true;
    		int local_loop = 0;
    		while (local_loop < NoBytesRead)
    		{
    			m_pInData[local_loop] = ReadData[local_loop];
    			++local_loop;
    			//m_pInData now holds the received message.
    
    		}
    		//We need to process it next to ensure it is valid
    		InteractDlg::ProcessOfficeMessage();
    	}
    	//Finally, after we've processed whatever we need to do and send a
    	//response, we go back to listening
    }
    Yes, all your serial port read/write operations should be moved into the secondary (worker) thread(s). The main GUI thread should be then notified from a worker thread about what you need to get info,
    Note also that the notifications have to be implemented using PostMessage (neither SendMessage nor direct access to the GUI thread objects!)
    Victor Nijegorodov

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