2015-02-04 3 views
3

Я написал этот код ниже, и он отлично работал под кодом :: blocks, используя mingw gcc 4.7 для его компиляции. С тех пор я решил начать использовать Visual Studio 2013 express. Теперь я получаю сообщение об ошибке при вызове ReadFile(). Что представляется недопустимым параметром. Я не вижу ошибки в надежде, что кто-то здесь сможет это заметить.WIN API ReadFile() возвращает GetLastError() ERROR_INVALID_PARAMETER

Все это завернуто в класс Serial. Из того, что я вижу в IDE, ссылка на память для m_hSerial правильна по сравнению с ссылкой CreateFile(), возвращаемой в дескриптор.

m_hSerial = CreateFile(m_pchPort, 
         GENERIC_READ | GENERIC_WRITE, 
         0, 
         0, 
         OPEN_EXISTING, 
         FILE_FLAG_OVERLAPPED, 
         0); 

я называю WorkThread как так

m_hThread = (HANDLE)_beginthreadex(0, 0, &WorkThread, (void*) this, 0, 0); 

Вот код WorkThread

unsigned int __stdcall Serial::WorkThread(void* pvParam) 
{ 
// This is a pointer to the 'this' serial class. 
// Needed to be able to set members of the class in a static class function 
Serial * cThis = (Serial*) pvParam; 
// Set up the overlapped event 
OVERLAPPED ov; 
memset(&ov, 0, sizeof(ov)); 
ov.hEvent = CreateEvent(0, true, 0, 0); 
DWORD dwEventMask = 0; 
DWORD dwWait; 
HANDLE aHandles[2]; 
aHandles[0] = cThis->m_hThreadTerminator; 
aHandles[1] = ov.hEvent; 

SetEvent(cThis->m_hThreadRunning); 
while (true) 
{ 
    if (!WaitCommEvent(cThis->m_hSerial, &dwEventMask, &ov)) 
    { 
     assert(GetLastError() == ERROR_IO_PENDING); 

    } 

    dwWait = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE); 
    switch(dwWait) 
    { 
     case WAIT_OBJECT_0: 
     { 
      _endthreadex(1); 
     } 
     case WAIT_OBJECT_0 + 1: 
     { 
      if (dwEventMask & EV_TXEMPTY) 
      { 
       ResetEvent(ov.hEvent); 
      } 
      else if (dwEventMask & EV_RXCHAR) 
      { 
       // read data here 
       DWORD dwBytesRead = 0; 
       DWORD dwErrors; 
       COMSTAT cStat; 
       OVERLAPPED ovRead; 
       ovRead.hEvent = CreateEvent(0, true, 0, 0); 

       // Get the Bytes in queue 
       ClearCommError(cThis->m_hSerial, &dwErrors, &cStat); 
       DWORD nSize = cStat.cbInQue; 
       // EM_REPLACESEL needs a LPARAM null terminated string, make room and set the CString NULL 
       char *szBuf = new char[nSize+1]; 
       memset(szBuf, 0x00, sizeof(szBuf)); 

       if (!ReadFile(cThis->m_hSerial, &szBuf, nSize, &dwBytesRead, &ovRead)) 
        DWORD err = GetLastError(); 
       if (dwBytesRead == nSize) 
        SendMessage(cThis->m_hHwnd, WM_SERIAL, 0, LPARAM(&szBuf)); 

       CloseHandle(ovRead.hEvent); // clean up!!! 
       delete[] szBuf; 
      } 
      // Reset the overlapped event 
      ResetEvent(ov.hEvent); 
     } 
     break; 
    }//switch 
} 

return 0; 

}

+0

Почему вы нарушаете 'szBuf' при вызове' ReadFile() '? Передавая szBuf напрямую, вы неявно делаете '& szBuf [0]', что должно быть правильным подходом для вызова этой функции. – Vinzenz

+0

Вы забыли правильно инициализировать ovRead, используйте 'OVERLAPPED ovRead = {};' –

+0

@HansPassant, вы были правы, это была моя ошибка. Отправьте его как ответ, и я приму его. – user188757

ответ

4
ReadFile(cThis->m_hSerial, &szBuf, nSize, &dwBytesRead, &ovRead) 

вы просите асинхронной операции, но и попросив функцию рассказать вам, как было прочитано много байтов. Вы выбрали &dwBytesRead как предпоследний параметр. Когда вы выполняете перекрывающиеся чтения, перейдите NULL для этого параметра. documentation говорит:

Используйте NULL для этого параметра, если это асинхронная операция, чтобы избежать потенциально ошибочных результатов.

также является ошибкой пройти &szBuf в приведенном выше коде. Вы хотите пройти szBuf.

Вы также не можете инициализировать структуру OVERLAPPED. Делайте это так:

OVERLAPPED ovRead = {}; 

Большая проблема в том, что вы просите асинхронного доступа, а затем написать код, как это это были синхронны. Как только ReadFile вернет вам попытку получить значимую информацию из dwBytesRead и вы закроете событие, которое вы положили в перекрываемую структуру.

Если вы действительно выполняете код асинхронно, вам нужно переписать код как асинхронный. На первый взгляд кажется, что вы не полностью поняли последствия перекрывающихся операций ввода-вывода, и вы, возможно, должны переключиться на неперекрывающийся синхронный ввод-вывод.

+0

Вы хотите передать '& szBuf [0]' * – Vinzenz

+0

@Vinzenz Silly typo, 'szBuf' - это то, что я имел в виду, теперь исправлено, спасибо –

+0

да, но вы написали' & szBuf' вместо 'szBuf'. Также это просто язык. В конце 'szBuf' и' & szBuf [0] 'одинаковы;) – Vinzenz

Смежные вопросы