WaitCommEvent 在第二次传递时失败,参数无效

发布于 2024-11-07 17:33:14 字数 17352 浏览 5 评论 0原文

我的应用程序使用具有重叠事件的串行 I/O。由于某种原因,::WaitCommEvent 在第二次循环时始终失败,并出现 ERROR_INVALID_PARAMETER。如果有人能解释我需要做什么不同的事情,我将不胜感激。我的串口初始化/打开代码和线程函数如下。需要注意的是,init/open 代码是在线程函数启动之后执行的,这就是调用 ::WaitForSingleObject 的目的。

此外,我想知道像 ::WaitForSingleObject( pobjSerialPort->m_hSerialPort, INFINITE ); 这样的东西是否可以作为确定串行端口何时打开的非阻塞方法有效。

串行端口初始化:

DWORD CSerialPort::Open( const wchar_t * portName )
{
    DCB dcb = {0};
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        if ( this->IsOpen() != FALSE )
        {
            TRACE(_T("CSerialPort::Open : Warning: Attempted to re-open serial port that is already open.\r\n"));
            continue;
        }

        // Overwrite port name if specified.
        if ( portName != NULL )
        {
            this->m_pwcPortName.clear();
            this->m_pwcPortName.append( SP_NAME_PREFIX );
            this->m_pwcPortName.append( portName );
        }

        ASSERT(this->m_pwcPortName.length() > 0);

        // Open the serial port.
        if ( (this->m_hSerialPort = ::CreateFile(
            m_pwcPortName.c_str(),          // Formatted serial port name
            GENERIC_READ | GENERIC_WRITE,   // Access: Read and write
            0,                              // Share: No sharing
            NULL,                           // Security: None
            OPEN_EXISTING,                  // COM port already exists
            FILE_FLAG_OVERLAPPED,           // Asynchronous I/O
            NULL                            // No template file for COM port
            )) == INVALID_HANDLE_VALUE )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to get the handle to the serial port.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Initialize the DCB structure with COM port parameters.
        if ( !::BuildCommDCB( _T("baud=38400 parity=N data=8 stop=1"), &dcb ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to build the DCB structure.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set the serial port communications events mask.
        if ( !::SetCommMask( this->m_hSerialPort, SP_COMM_MASK ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set comm. events to be monitored.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set serial port parameters.
        if ( !::SetCommState( this->m_hSerialPort, &dcb ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set the comm state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set the serial port communications timeouts.
        this->m_ct.ReadIntervalTimeout = MAXDWORD;
        this->m_ct.ReadTotalTimeoutMultiplier = 0;
        this->m_ct.ReadTotalTimeoutConstant = 0;
        this->m_ct.WriteTotalTimeoutMultiplier = 0;
        this->m_ct.WriteTotalTimeoutConstant = 0;

        if ( !::SetCommTimeouts( this->m_hSerialPort, &(this->m_ct) ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set the comm timeout values.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Create thread to receive data.
        if ( (this->m_hSpRxThread = CreateThread(
            NULL,                           // No security attributes.
            0,                              // Use default initial stack size.
            reinterpret_cast<LPTHREAD_START_ROUTINE>(SerialPortRxThreadFn), // Function to execute in new thread.
            this,                           // Thread parameters.
            0,                              // Use default creation settings.
            NULL                            // Thread ID is not needed.
            )) == NULL )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to create serial port receive thread.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Create thread to transmit data.
        if ( (this->m_hSpTxThread = CreateThread(
            NULL,                           // No security attributes.
            0,                              // Use default initial stack size.
            reinterpret_cast<LPTHREAD_START_ROUTINE>(SerialPortTxThreadFn), // Function to execute in new thread.
            this,                           // Thread parameters.
            0,                              // Use default creation settings.
            NULL                            // Thread ID is not needed.
            )) == NULL )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to create serial port transmit thread.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( !::SetEvent( this->m_hSpPortOpenEvent ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }
    }
    while ( 0 );

    return dwError;
}

串行端口通信事件线程:

static DWORD SerialPortCommEvtsThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovComm = { 0 };
    int i = 0;
    static HANDLE pHandles[SPCM_MAX_EVENTS + SP_ONE_ITEM]; // +1 for overlapped event

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortTxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    pobjSerialPort = (CSerialPort *)pParam;

    // Load event handles.
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_THREAD_EXIT_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID );

    while ( (blContinue != FALSE) && (dwError == ERROR_SUCCESS) )
    {
        // Wait for serial port to open.
        if ( (dwObjectWaitState = ::WaitForSingleObject( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ), INFINITE )) != WAIT_OBJECT_0 )
        {
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( ovComm.hEvent == NULL )
        {
            // Create event object for serial port communications events OVERLAPPED structure.
            if ( (ovComm.hEvent = ::CreateEvent(
                NULL,                           // No security
                TRUE,                           // Create a manual-reset event object
                FALSE,                          // Initial state is non-signaled
                NULL                            // No name specified
                )) == NULL )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to create event object.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            pHandles[i++] = ovComm.hEvent;
        }
        else
        {
            i++;
        }

        // Wait for a communications event.
        if ( !::WaitCommEvent( pobjSerialPort->m_hSerialPort, &dwEventMask, &ovComm ) )
        {
            if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            else
            {
                dwError = ERROR_SUCCESS;
            }
        }
        else
        {
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            continue;
        }

        dwObjectWaitState = ::WaitForMultipleObjects( i--, pHandles, FALSE, INFINITE );

        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPCM_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_OPEN_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_CLOSED_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_MAX_EVENTS:
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            ::CloseHandle( ovComm.hEvent );
            ::memset( &ovComm, 0, sizeof(OVERLAPPED) );
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}

处理通信事件函数

static DWORD HandleCommOvEvent( CSerialPort * pobjSerialPort, DWORD dwEvtMask )
{
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        // Validate parameters.
        if ( pobjSerialPort == NULL )
        {
            dwError = ERROR_INVALID_PARAMETER;
            TRACE(_T("HandleCommEvent : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Handle the transmit complete event.
        if ( dwEvtMask & EV_TXEMPTY )
        {
            if ( (dwError = HandleTxDoneCommEvent( pobjSerialPort )) != ERROR_SUCCESS )
            {
                TRACE(_T("HandleCommEvent : Failed handling transmit complete event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
        }

        // Handle the received data event.
        if ( dwEvtMask & EV_RXCHAR )
        {
            if ( (dwError = HandleRxDataCommEvent( pobjSerialPort )) != ERROR_SUCCESS )
            {
                TRACE(_T("HandleCommEvent : Failed handling received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
        }
    }
    while ( 0 );

    return dwError;
}

处理接收到的数据通信事件函数

static DWORD HandleRxDataCommEvent( CSerialPort * pobjSerialPort )
{
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        // Validate parameters.
        if ( pobjSerialPort == NULL )
        {
            dwError = ERROR_INVALID_PARAMETER;
            TRACE(_T("HandleRxDataCommEvent : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( !::SetEvent( pobjSerialPort->GetRxHandle( SPRX_RECEIVED_DATA_EVT_ID ) ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("HandleRxDataCommEvent : Failed setting event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }
    }
    while ( 0 );

    return dwError;
}

接收线程函数

static DWORD SerialPortRxThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovComm = { 0 };
    int i = 0;
    static BYTE pBuf[SP_RX_BUF_SIZE];
    static HANDLE pHandles[SPRX_MAX_EVENTS + SP_ONE_ITEM]; // +1 for overlapped event

    ASSERT(s_pobjRxBuffer != NULL);

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortRxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    pobjSerialPort = (CSerialPort *)pParam;

    // Load event handles.
    pHandles[i++] = pobjSerialPort->GetRxHandle( SPRX_THREAD_EXIT_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetRxHandle( SPRX_RECEIVED_DATA_EVT_ID );

    while ( (blContinue != FALSE) && (dwError == ERROR_SUCCESS) )
    {
        if ( ovComm.hEvent == NULL )
        {
            // Create event object for serial port communications events OVERLAPPED structure.
            if ( (ovComm.hEvent = ::CreateEvent(
                NULL,                           // No security
                TRUE,                           // Create a manual-reset event object
                FALSE,                          // Initial state is non-signaled
                NULL                            // No name specified
                )) == NULL )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortRxThreadFn : Failed to create event object.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            pHandles[i++] = ovComm.hEvent;
        }
        else
        {
            i++;
        }

        dwObjectWaitState = ::WaitForMultipleObjects( i--, pHandles, FALSE, INFINITE );

        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPRX_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPRX_RECEIVED_DATA_EVT_ID:
            if ( !::ReadFile( pobjSerialPort->m_hSerialPort, pBuf, SP_RX_BUF_SIZE, NULL, &ovComm ) )
            {
                if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING )
                {
                    TRACE(_T("SerialPortRxThreadFn : Failed reading data from serial port.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                    continue;
                }
            }
            else
            {
                if ( (dwError = HandleReceivedDataOvEvent( pobjSerialPort, &ovComm, pBuf )) != ERROR_SUCCESS )
                {
                    TRACE(_T("SerialPortRxThreadFn : Failed handling serial port received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                    continue;
                }
            }
            break;

        case WAIT_OBJECT_0 + SPRX_MAX_EVENTS:
            if ( (dwError = HandleReceivedDataOvEvent( pobjSerialPort, &ovComm, pBuf )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortRxThreadFn : Failed handling serial port received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            ::CloseHandle( ovComm.hEvent );
            ::memset( &ovComm, 0, sizeof(OVERLAPPED) );
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortRxThreadFn : There is a problem with the OVERLAPPED structure's event handle.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}

My application uses serial I/O with overlapped events. For some reason, ::WaitCommEvent fails consistently on the second pass through the loop with ERROR_INVALID_PARAMETER. If anyone can explain what I need to do differently, it would be greatly appreciated. My serial port initialization/open code and the thread function follows. It should be noted that the init/open code is executed after the thread function is started, which is what the call to ::WaitForSingleObject for.

Additionally, I was wondering if something like ::WaitForSingleObject( pobjSerialPort->m_hSerialPort, INFINITE ); would be valid as a non-blocking means of determining when the serial port is open.

Serial Port Initialization:

DWORD CSerialPort::Open( const wchar_t * portName )
{
    DCB dcb = {0};
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        if ( this->IsOpen() != FALSE )
        {
            TRACE(_T("CSerialPort::Open : Warning: Attempted to re-open serial port that is already open.\r\n"));
            continue;
        }

        // Overwrite port name if specified.
        if ( portName != NULL )
        {
            this->m_pwcPortName.clear();
            this->m_pwcPortName.append( SP_NAME_PREFIX );
            this->m_pwcPortName.append( portName );
        }

        ASSERT(this->m_pwcPortName.length() > 0);

        // Open the serial port.
        if ( (this->m_hSerialPort = ::CreateFile(
            m_pwcPortName.c_str(),          // Formatted serial port name
            GENERIC_READ | GENERIC_WRITE,   // Access: Read and write
            0,                              // Share: No sharing
            NULL,                           // Security: None
            OPEN_EXISTING,                  // COM port already exists
            FILE_FLAG_OVERLAPPED,           // Asynchronous I/O
            NULL                            // No template file for COM port
            )) == INVALID_HANDLE_VALUE )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to get the handle to the serial port.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Initialize the DCB structure with COM port parameters.
        if ( !::BuildCommDCB( _T("baud=38400 parity=N data=8 stop=1"), &dcb ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to build the DCB structure.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set the serial port communications events mask.
        if ( !::SetCommMask( this->m_hSerialPort, SP_COMM_MASK ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set comm. events to be monitored.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set serial port parameters.
        if ( !::SetCommState( this->m_hSerialPort, &dcb ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set the comm state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Set the serial port communications timeouts.
        this->m_ct.ReadIntervalTimeout = MAXDWORD;
        this->m_ct.ReadTotalTimeoutMultiplier = 0;
        this->m_ct.ReadTotalTimeoutConstant = 0;
        this->m_ct.WriteTotalTimeoutMultiplier = 0;
        this->m_ct.WriteTotalTimeoutConstant = 0;

        if ( !::SetCommTimeouts( this->m_hSerialPort, &(this->m_ct) ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set the comm timeout values.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Create thread to receive data.
        if ( (this->m_hSpRxThread = CreateThread(
            NULL,                           // No security attributes.
            0,                              // Use default initial stack size.
            reinterpret_cast<LPTHREAD_START_ROUTINE>(SerialPortRxThreadFn), // Function to execute in new thread.
            this,                           // Thread parameters.
            0,                              // Use default creation settings.
            NULL                            // Thread ID is not needed.
            )) == NULL )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to create serial port receive thread.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Create thread to transmit data.
        if ( (this->m_hSpTxThread = CreateThread(
            NULL,                           // No security attributes.
            0,                              // Use default initial stack size.
            reinterpret_cast<LPTHREAD_START_ROUTINE>(SerialPortTxThreadFn), // Function to execute in new thread.
            this,                           // Thread parameters.
            0,                              // Use default creation settings.
            NULL                            // Thread ID is not needed.
            )) == NULL )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to create serial port transmit thread.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( !::SetEvent( this->m_hSpPortOpenEvent ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("CSerialPort::Open : Failed to set event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }
    }
    while ( 0 );

    return dwError;
}

Serial Port Communications Events Thread:

static DWORD SerialPortCommEvtsThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovComm = { 0 };
    int i = 0;
    static HANDLE pHandles[SPCM_MAX_EVENTS + SP_ONE_ITEM]; // +1 for overlapped event

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortTxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    pobjSerialPort = (CSerialPort *)pParam;

    // Load event handles.
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_THREAD_EXIT_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID );

    while ( (blContinue != FALSE) && (dwError == ERROR_SUCCESS) )
    {
        // Wait for serial port to open.
        if ( (dwObjectWaitState = ::WaitForSingleObject( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ), INFINITE )) != WAIT_OBJECT_0 )
        {
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( ovComm.hEvent == NULL )
        {
            // Create event object for serial port communications events OVERLAPPED structure.
            if ( (ovComm.hEvent = ::CreateEvent(
                NULL,                           // No security
                TRUE,                           // Create a manual-reset event object
                FALSE,                          // Initial state is non-signaled
                NULL                            // No name specified
                )) == NULL )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to create event object.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            pHandles[i++] = ovComm.hEvent;
        }
        else
        {
            i++;
        }

        // Wait for a communications event.
        if ( !::WaitCommEvent( pobjSerialPort->m_hSerialPort, &dwEventMask, &ovComm ) )
        {
            if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            else
            {
                dwError = ERROR_SUCCESS;
            }
        }
        else
        {
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            continue;
        }

        dwObjectWaitState = ::WaitForMultipleObjects( i--, pHandles, FALSE, INFINITE );

        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPCM_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_OPEN_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_CLOSED_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_MAX_EVENTS:
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            ::CloseHandle( ovComm.hEvent );
            ::memset( &ovComm, 0, sizeof(OVERLAPPED) );
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}

Handle Comm Events Function

static DWORD HandleCommOvEvent( CSerialPort * pobjSerialPort, DWORD dwEvtMask )
{
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        // Validate parameters.
        if ( pobjSerialPort == NULL )
        {
            dwError = ERROR_INVALID_PARAMETER;
            TRACE(_T("HandleCommEvent : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        // Handle the transmit complete event.
        if ( dwEvtMask & EV_TXEMPTY )
        {
            if ( (dwError = HandleTxDoneCommEvent( pobjSerialPort )) != ERROR_SUCCESS )
            {
                TRACE(_T("HandleCommEvent : Failed handling transmit complete event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
        }

        // Handle the received data event.
        if ( dwEvtMask & EV_RXCHAR )
        {
            if ( (dwError = HandleRxDataCommEvent( pobjSerialPort )) != ERROR_SUCCESS )
            {
                TRACE(_T("HandleCommEvent : Failed handling received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
        }
    }
    while ( 0 );

    return dwError;
}

Handle Received Data Comm Event Function

static DWORD HandleRxDataCommEvent( CSerialPort * pobjSerialPort )
{
    DWORD dwError = ERROR_SUCCESS;

    do
    {
        // Validate parameters.
        if ( pobjSerialPort == NULL )
        {
            dwError = ERROR_INVALID_PARAMETER;
            TRACE(_T("HandleRxDataCommEvent : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }

        if ( !::SetEvent( pobjSerialPort->GetRxHandle( SPRX_RECEIVED_DATA_EVT_ID ) ) )
        {
            dwError = ::GetLastError();
            TRACE(_T("HandleRxDataCommEvent : Failed setting event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            continue;
        }
    }
    while ( 0 );

    return dwError;
}

Receive Thread Function

static DWORD SerialPortRxThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovComm = { 0 };
    int i = 0;
    static BYTE pBuf[SP_RX_BUF_SIZE];
    static HANDLE pHandles[SPRX_MAX_EVENTS + SP_ONE_ITEM]; // +1 for overlapped event

    ASSERT(s_pobjRxBuffer != NULL);

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortRxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    pobjSerialPort = (CSerialPort *)pParam;

    // Load event handles.
    pHandles[i++] = pobjSerialPort->GetRxHandle( SPRX_THREAD_EXIT_EVT_ID );
    pHandles[i++] = pobjSerialPort->GetRxHandle( SPRX_RECEIVED_DATA_EVT_ID );

    while ( (blContinue != FALSE) && (dwError == ERROR_SUCCESS) )
    {
        if ( ovComm.hEvent == NULL )
        {
            // Create event object for serial port communications events OVERLAPPED structure.
            if ( (ovComm.hEvent = ::CreateEvent(
                NULL,                           // No security
                TRUE,                           // Create a manual-reset event object
                FALSE,                          // Initial state is non-signaled
                NULL                            // No name specified
                )) == NULL )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortRxThreadFn : Failed to create event object.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            pHandles[i++] = ovComm.hEvent;
        }
        else
        {
            i++;
        }

        dwObjectWaitState = ::WaitForMultipleObjects( i--, pHandles, FALSE, INFINITE );

        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPRX_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPRX_RECEIVED_DATA_EVT_ID:
            if ( !::ReadFile( pobjSerialPort->m_hSerialPort, pBuf, SP_RX_BUF_SIZE, NULL, &ovComm ) )
            {
                if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING )
                {
                    TRACE(_T("SerialPortRxThreadFn : Failed reading data from serial port.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                    continue;
                }
            }
            else
            {
                if ( (dwError = HandleReceivedDataOvEvent( pobjSerialPort, &ovComm, pBuf )) != ERROR_SUCCESS )
                {
                    TRACE(_T("SerialPortRxThreadFn : Failed handling serial port received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                    continue;
                }
            }
            break;

        case WAIT_OBJECT_0 + SPRX_MAX_EVENTS:
            if ( (dwError = HandleReceivedDataOvEvent( pobjSerialPort, &ovComm, pBuf )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortRxThreadFn : Failed handling serial port received data event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            ::CloseHandle( ovComm.hEvent );
            ::memset( &ovComm, 0, sizeof(OVERLAPPED) );
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortRxThreadFn : There is a problem with the OVERLAPPED structure's event handle.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

哭了丶谁疼 2024-11-14 17:33:15

您正在调用

WaitCommEvent(pobjSerialPort->m_hSerialPort, &dwEventMask, &(pobjSerialPort->m_ovEvents))

WaitCommEvent 的第一个和第三个参数是输入参数,但是您没有提供它们的初始化代码。

如何初始化m_hSerialPort?您是否使用有效参数调用 CreateFile 并验证没有错误?
如何初始化 m_ovEvents?您是否使用有效参数调用 CreateEvent 并验证没有错误?

由于您收到 ERROR_INVALID_PARAMETER,我认为您的问题在于这些参数之一的初始化。

You are calling

WaitCommEvent(pobjSerialPort->m_hSerialPort, &dwEventMask, &(pobjSerialPort->m_ovEvents))

The 1st and 3rd parameters of WaitCommEvent are input parameters, However you did not supply their initialization code.

How do you initialize m_hSerialPort? Do you call CreateFile with valid params and verify there is no error?
How do you initialize m_ovEvents? Do you call CreateEvent with valid params and verify there is no error?

Since you're getting ERROR_INVALID_PARAMETER, I think your problem is in the initialization of one of these parameters.

绅刃 2024-11-14 17:33:14

看起来您正在尝试对 WaitCommEventReadFile 使用相同的 OVERLAPPED 结构。这应该会给你带来无穷无尽的问题。


文档引用: 在单个线程上同时执行多个重叠操作时,调用线程必须指定每个操作的重叠结构


尝试修复它(未测试,甚至未编译)。您需要针对您的项目填写的内容标有 // TODO

static DWORD SerialPortCommEvtsThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovWaitComm = { 0 };
    OVERLAPPED ovRead = { 0 };
    const DWORD numHandles = SPCM_MAX_EVENTS + 2;
    HANDLE pHandles[numHandles];

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortTxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }
    pobjSerialPort = static_cast<CSerialPort *>(pParam);

    ovWaitComm.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    ovRead.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!ovWaitComm.hEvent || !ovRead.hEvent) {
        dwError = ::GetLastError();
        TRACE(_T("SerialPortCommEvtsThreadFn : Failed to create event objects.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    // Load event handles.
    pHandles[SPCM_THREAD_EXIT_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_THREAD_EXIT_EVT_ID );
    pHandles[SPCM_PORT_OPEN_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID );
    pHandles[SPCM_PORT_CLOSED_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID );
    pHandles[numHandles - 2] = ovWaitComm.hEvent;
    pHandles[numHandles - 1] = ovRead.hEvent;

    // Wait for serial port to open.
    if ( (dwObjectWaitState = ::WaitForSingleObject( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ), INFINITE )) != WAIT_OBJECT_0 ) {
        dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
        TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    // TODO: SetCommTimeouts

    // Wait for a communications event.
    if ( !::WaitCommEvent( pobjSerialPort->m_hSerialPort, &dwEventMask, &ovWaitComm ) {
        if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING ) {
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            return dwError;
        }
    }

    // TODO: Here, call ReadFile, passing &ovRead

    dwError = ERROR_SUCCESS;
    while ( blContinue && (dwError == ERROR_SUCCESS) )
    {
        dwObjectWaitState = ::WaitForMultipleObjects( numHandles, pHandles, FALSE, INFINITE );
        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPCM_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_OPEN_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_CLOSED_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + numHandles - 2:
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            // TODO: call WaitCommEvent again, if HandleCommOvEvent didn't already
            break;

        case WAIT_OBJECT_0 + numHandles - 1:
            // TODO: do something with the received data, it's now in the buffer supplied to ReadFile
            // TODO: call ReadFile again
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}

Looks like you're trying to use the same OVERLAPPED structure for both WaitCommEvent and ReadFile. That should be causing you no end of problems.


Documentation citation: When performing multiple simultaneous overlapped operations on a single thread, the calling thread must specify an OVERLAPPED structure for each operation


An attempt to fix it (not tested, not even compiled). Stuff you need to fill in specific to your project is marked with // TODO.

static DWORD SerialPortCommEvtsThreadFn( void * pParam )
{
    CSerialPort * pobjSerialPort = NULL;
    BOOL blContinue = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwEventMask = 0;
    DWORD dwObjectWaitState;
    OVERLAPPED ovWaitComm = { 0 };
    OVERLAPPED ovRead = { 0 };
    const DWORD numHandles = SPCM_MAX_EVENTS + 2;
    HANDLE pHandles[numHandles];

    // Validate parameters.
    if ( pParam == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        TRACE(_T("SerialPortTxThreadFn : Invalid parameter.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }
    pobjSerialPort = static_cast<CSerialPort *>(pParam);

    ovWaitComm.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    ovRead.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!ovWaitComm.hEvent || !ovRead.hEvent) {
        dwError = ::GetLastError();
        TRACE(_T("SerialPortCommEvtsThreadFn : Failed to create event objects.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    // Load event handles.
    pHandles[SPCM_THREAD_EXIT_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_THREAD_EXIT_EVT_ID );
    pHandles[SPCM_PORT_OPEN_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID );
    pHandles[SPCM_PORT_CLOSED_EVT_ID ] = pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID );
    pHandles[numHandles - 2] = ovWaitComm.hEvent;
    pHandles[numHandles - 1] = ovRead.hEvent;

    // Wait for serial port to open.
    if ( (dwObjectWaitState = ::WaitForSingleObject( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ), INFINITE )) != WAIT_OBJECT_0 ) {
        dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
        TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
        return dwError;
    }

    // TODO: SetCommTimeouts

    // Wait for a communications event.
    if ( !::WaitCommEvent( pobjSerialPort->m_hSerialPort, &dwEventMask, &ovWaitComm ) {
        if ( (dwError = ::GetLastError()) != ERROR_IO_PENDING ) {
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            return dwError;
        }
    }

    // TODO: Here, call ReadFile, passing &ovRead

    dwError = ERROR_SUCCESS;
    while ( blContinue && (dwError == ERROR_SUCCESS) )
    {
        dwObjectWaitState = ::WaitForMultipleObjects( numHandles, pHandles, FALSE, INFINITE );
        switch ( dwObjectWaitState )
        {
        case WAIT_OBJECT_0 + SPCM_THREAD_EXIT_EVT_ID:
            blContinue = FALSE;
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_OPEN_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_CLOSED_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + SPCM_PORT_CLOSED_EVT_ID:
            if ( !::ResetEvent( pobjSerialPort->GetCommHandle( SPCM_PORT_OPEN_EVT_ID ) ) )
            {
                dwError = ::GetLastError();
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed to reset event object signal state.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }
            break;

        case WAIT_OBJECT_0 + numHandles - 2:
            if ( (dwError = HandleCommOvEvent( pobjSerialPort, dwEventMask )) != ERROR_SUCCESS )
            {
                TRACE(_T("SerialPortCommEvtsThreadFn : Failed handling communications event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
                continue;
            }

            // TODO: call WaitCommEvent again, if HandleCommOvEvent didn't already
            break;

        case WAIT_OBJECT_0 + numHandles - 1:
            // TODO: do something with the received data, it's now in the buffer supplied to ReadFile
            // TODO: call ReadFile again
            break;

        default:
            dwError = ( dwObjectWaitState == WAIT_FAILED ) ? ::GetLastError() : dwObjectWaitState;
            TRACE(_T("SerialPortCommEvtsThreadFn : Failed waiting for event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwError, _T(__FILE__), __LINE__);
            break;
        }
    }

    return dwError;
}
梦里人 2024-11-14 17:33:14

当您没有检查是否存在错误时,您似乎正在调用 GetLastError() 。

It looks like you're calling GetLastError() when you haven't checked that there's been an error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文