Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: И снова работа с COM-портом (в асинхронном режиме)  (Прочитано 28045 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
asker
Помогающий

ru
Offline Offline
Пол: Мужской

« : 17-05-2007 07:54 » 

Всем привет!
Не ругайтесь, что снова завожу тему про работу с com-портом.
Я просмотрел все материалы, которые нашел на сайте и в Интернете (не всеБ конечно, т.к. это невозможно).

В общем такая ситуация:
Я работаю с портом в асинхронном режиме.
 У меня есть поток, который читает данные и основной процесс, в котором я пишу данные в порт.

В итоге он постоянно мне выводит "Протекает наложенное событие ввода-вывода". Даже если он отправляет в порт, то не читает. Я этот класс давно написал, и раньше вроде все работало, а сейчас...
Да, когда писал, основывался в основном на книге Агурова
Привожу код:
Инициализирую:
Код:
               // чистка структуры
memset(&m_dcb,0,sizeof(m_dcb));
// заносим значения по умолчанию
m_dcb.DCBlength = sizeof(m_dcb);
m_dcb.BaudRate = CBR_9600;
m_dcb.ByteSize = 8;
m_dcb.fParity = NOPARITY;
m_dcb.StopBits = ONESTOPBIT;
// Windows поддерживает только бинарный режим работы
m_dcb.fBinary = 1;

               // Устанавливаем тайм-ауты по умолчанию
m_commTimeouts.ReadIntervalTimeout = MAXDWORD; // MAXDWORD
m_commTimeouts.ReadTotalTimeoutConstant = 0;
m_commTimeouts.ReadTotalTimeoutMultiplier = 0;
m_commTimeouts.WriteTotalTimeoutConstant = 0; //200
m_commTimeouts.WriteTotalTimeoutMultiplier = 0;

Открываю порт
Код:
void CComPort::DoOpenPort()
{
CString comName;

// Если порт открыт, то выходим
if (GetConnected()) return;

// Имя порта
comName.Format("\\\\.\\COM%-d", m_nComNumber);

// Открытие последовательного порта
m_handle = CreateFile(comName, GENERIC_READ | GENERIC_WRITE,
0, // неразделяемый ресурс
NULL, // нет атрибутов защиты
OPEN_EXISTING, // вернуть ошибку, если ресурс не существует
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // асинхронный режим доступа
NULL // должно быть NULL для COM-портов
);

// Если ошибка открытия порта, то генерируем сообщение "Отказано в доступе"
if (!GetConnected())
throw ERROR_ACCESS_DENIED;
// Инициализация порта
ApplyComSettings();
ApplyComTimeouts();
}

Пишу в буфер
Код:
bool CComPort::WriteBuffer(const BYTE* buffer, const int size)
{
DWORD realWrite, signaled, bytesTrans, mask;
OVERLAPPED writeOL; // структура для асинхронной записи
        bool ret;

// создание событие для асинхронной записи
memset(&writeOL, 0, sizeof(writeOL));
writeOL.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
// начало асинхронной записи
if (WriteFile(m_handle, buffer, size, &realWrite, &writeOL) == 0)
if (GetLastError() != ERROR_IO_PENDING) {
CloseHandle(writeOL.hEvent);
return false;
}
// ожидание завершения асихронной операции и получение результата
signaled = WaitForSingleObject(writeOL.hEvent, INFINITE);
ret = signaled == WAIT_OBJECT_0 && GetOverlappedResult(m_handle, &writeOL, &bytesTrans, FALSE);
// Закрытие дескриптора сигнального объекта
CloseHandle(writeOL.hEvent);
return ret;
}

И, наконец, читаю
Код:
UINT ReadDataFromPortOfGSMModem(LPVOID pParam)
{
DWORD avaibleBytes, // Число полученных, но не прочитанных байт
 errCode, // Код ошибки
 realRead,
 signaled,
 mask,
 bytesTrans, // Не испльзуется для WaitCommEvent
 dwCurSizeBuf = 0; // Текущий размер буфера, т.е. сколько байт данных в буфере
OVERLAPPED readOL; // Структура для асинхронного чтения
BYTE inBuffer[MAX_SIZE_BUFFER]; // Буфер приема
COMSTAT currentState;
UINT ret = 0;

CSmsSender* pSender = (CSmsSender*) pParam;
CComPort* pPort = (CComPort*) pSender->GetPort();

try {
// очистка буфера
memset(inBuffer, 0, sizeof inBuffer);
// создание событие для асинхронного чтения
readOL.Internal = readOL.InternalHigh = readOL.Offset = readOL.OffsetHigh = 0;

readOL.hEvent = CreateEvent(NULL,// аттрибуты защиты такие же как и у родительского процесса
TRUE, // режим управления событием ручной
TRUE, // в сигнальном состоянии
NULL); // безымянный

while (pPort->GetConnected()) { // пока порт открыт

// Маска событий, которые будет отслеживать читающий поток
// Пока это только получение символа
SetCommMask(pPort->GetHandle(), EV_RXCHAR);// | EV_TXEMPTY
// Ждем одно из событий
WaitCommEvent(pPort->GetHandle(), &mask, &readOL);
// Ждем пока завершится операция чтения
signaled = WaitForSingleObject(readOL.hEvent, INFINITE);
switch (signaled) {
    case WAIT_OBJECT_0:
if (GetOverlappedResult(pPort->GetHandle(), &readOL, &bytesTrans, FALSE)) {
// После GetOverlappedResult в переменной mask, которая передавалась в WaitCommEvent,
// появятся флаги произошедших событий, либо 0 в случае ошибки
if (( mask & EV_RXCHAR ) != 0) {
// получаем состояние порта (линий и модема)
currentState = pPort->GetState(errCode);
// Число полученных, но не прочитанных байт
avaibleBytes = currentState.cbInQue;
if (avaibleBytes > 0) {
if (ReadFile(pPort->GetHandle(), (inBuffer + dwCurSizeBuf), avaibleBytes, &realRead, &readOL)) {
dwCurSizeBuf += avaibleBytes;
if (pSender->IsDataReceived(dwCurSizeBuf, inBuffer)) {
// Пакет получен полностью, предварительная обработка
pSender->GetCritSectWS_Buf()->Lock();
pSender->CopyToBuffer(dwCurSizeBuf, inBuffer);
pSender->GetCritSectWS_Buf()->Unlock();
// Установить событие
pSender->SetEvent();
// Обнулить текущий размер буфера, т.е. буфер пуст
dwCurSizeBuf = 0;
// очистка буфера
memset(inBuffer, 0, sizeof inBuffer);
}
}
}
}
}
break;
case WAIT_TIMEOUT:
// Действия, которые необходимо сделать, если превышен интервал ожидания
break;
case WAIT_FAILED:
// Ошибка вызова WaitForSingleObject
break;
}
}
}
catch(...) {
ret = 1;
}
// Закрытие дескриптора сигнального объекта
CloseHandle(readOL.hEvent);
// Сброс события и маски ожидания
SetCommMask(pPort->GetHandle(), 0);

return ret;
}

Подскажите, пожалуйста.
« Последнее редактирование: 14-04-2010 05:23 от Sel » Записан

С уважением, asker
korbian
Гость
« Ответ #1 : 17-05-2007 10:57 » 

asker, полный код приведи. Я схожую логику при работе с ком портом использую. И ничего подозрительного не вижу.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #2 : 17-05-2007 21:39 » 

При асинхронной работе все операции чтения и записи ставятся в очередь... В том числе и ожидание...
Пока ждешь запись и чтение не работают...

Происходит блокировка
Пользуйся CancelIO & Purge такими вот командами для очистки очереди при принудительном чтении и семафорами для общей памяти.
Записан

А птичку нашу прошу не обижать!!!
asker
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 18-05-2007 01:26 » 

korbian, я почти полный код и привел, если несчитать методов типа Запуска, останова, приостанова потока и методов типа Set и Get.
 
Код метода pSender->IsDataReceived(dwCurSizeBuf, inBuffer):
Код:
	int j;
short i, k = m_strWaitingStr.GetLength();
bool fl = (m_strWaitingStr != "DEFAULT");

static int i1 = 0;
TRACE("IsDataReceived :: %d, buf = %s, ret = ", i1++, (char*) pBuffer);

for(i = 0, j = 0; i < dwSize; i++) {
if (i + 4 < dwSize) {
if (pBuffer[i] == 'E' && pBuffer[i + 1] == 'R' && pBuffer[i + 2] == 'R' &&
pBuffer[i + 3] == 'O' && pBuffer[i + 4] == 'R') {
TRACE("true\n");
return true; // нашли ERROR
}
}
else if (i + 1 < dwSize) {
if (pBuffer[i] == 'O' && pBuffer[i + 1] == 'K') {
TRACE("true\n");
return true; // нашли OK
}
}
else if (fl && i + k < dwSize) {
for( ; (j < k && pBuffer[i + j] == m_strWaitingStr[j]); j++);
if (j == k) {
TRACE("true\n");
return true; // нашли строку, которую ждем
}
else
j = 0;
}
else {
TRACE("false\n");
return false; // мы ничего не нашли
}
}
TRACE("false\n");
return false;

Что же касается этого куска, то:
в строчках 1 и 3 получается указатель на критическую секцию CCriticalSection и выполняется блокировка и разблокировка.
pSender->GetCritSectWS_Buf()->Lock();
pSender->CopyToBuffer(dwCurSizeBuf, inBuffer);
pSender->GetCritSectWS_Buf()->Unlock();

Метод CopyToBuffer(dwCurSizeBuf, inBuffer) выглядит так:
Код:
void CSmsSender::CopyToBuffer(const DWORD dwSize, const char* pBuffer)
{
m_strBuffer = pBuffer;
}

CString m_strBuffer; - член класса.

korbian, ты этот код имел ввиду или что-то другое. Просто если весь приводить то очень много получится.

Гром я не совсем понял что ты сказал. Ведь с лучае записи я жду, чтобы данные отправились. Значит в этот момент мне прием данных и не нужен.
Потом когда я должен пользоваться Purge ведь я могу дать команду на отчистку, а до этой команды пришедшие данные уже в буфере и у меня будет потеря
или я не все отправил и даю команду Purge, то же потеря.
Тоже самое с CancelIO.

А у меня еще пару вопросов:
( mask & EV_RXCHAR ) != 0 - это правильно, вроде да, но...

Когда я должен пользоваться флагом EV_TXEMPTY при записи или чтении.
Вроде при записи. Тогда перед WriteFile я должен написать SetCommMask(m_handle, EV_TXEMPTY),
а после WriteFile и перед WFSO - WaitCommEvent(...). if (mask & EV_TXEMPTY) {WFSO...}.
Так ведь?

И последнее (правда это не совсем по теме).
Как мне узнать используемые параметры (DCB, тайм-ауты) порта на втором конце.
Т.е. я посылаю команды и жду данные от мобильника. Мобильник подключается к USB. Я связываюсь с мобильником через виртуальный com-порт.
Может все дело в настройках?
Записан

С уважением, asker
asker
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 18-05-2007 02:27 » 

Сейчас попробовал с обычным модемом, здесь все нормально. Т.е. отсылает и принимает. Так что похоже действительно все ошибки связаны с настройками порта.
Если работать через hyperTerminal с мобильником и воспользоваться прогой PortMon, то терминал устанавливает следующие параметры:
bufInsize=8192 bufOutSize=8192
size = 0
Stopbits: 1 Parity: None LenWord: 8
EOF: 0 ERR: 0 BRK: 0 EVT: 0 XON: 11 XOFF: 13
SHAKE: 80000009 REPLACE: 80000080 XonLimit: 80 XoffLimit: 200
RI: 10 RM: 0 RC: 0 WM: 0 WC: 5000
MASK RLSD ERR

Что такое SHAKE и REPLACE.
В DCB структуре есть поле frtsControl, которое может принимать значение RTS_CONTROL_HANDSHAKE.
Но когда я его установил SHAKE: 80 REPLACE: 00 (помойму либо тоже 80).
Или это настройки HyperTerminal'а и они так связываются со всеми - сейчас посмотрю..., придется отключиться. - да терминал и для моего модема тоже самое поставил.
так что...
Подскажите...
Я вчера до того дошел, что у меня комп при чтении из порта на функции получения статуса модема шел на перезагрузку ... и это не один раз, а раза 4.
Записан

С уважением, asker
vegor
Интересующийся

am
Offline Offline

« Ответ #5 : 01-03-2010 10:07 » 

здравствуйте всем,я в форумах в первие ,и просил бы не судить очень строго.  помогите пожалуйста , хочу реализовать приложение работающую с <COM> портом.А для проверки работы приложения коротко замыкаю(к.з.) ножки RD(Вх.) и TD(Вых.) , чтобы WriteFile дала данные а ReadFile считало бы те же данные с того же порта.
сначало создаю диологовое приложение <bbb> а потом например в OnInitDialog()-е создаю COM-порт
Код:
{
...

OVERLAPPED ovr;  

hCOM = CreateFileA("COM1", GENERIC_READ |GENERIC_WRITE, // создание синхронного порта
0,NULL,OPEN_EXISTING,NULL,NULL);
PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart
GetCommState(hCOM,&dcb);
SetCommState(hCOM,&dcb);
SetCommTimeouts(hCOM,&to);

SetupComm(hCOM,in,out);

//memset(&ovr,0,sizeof(ovr));
//ovr.hEvent =::CreateEventA(NULL,FALSE,FALSE,NULL);

PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart

int in = 0;
 int out = 0;

return TRUE;  // return TRUE  unless you set the focus to a control
}
потом создаю кнопку и в нем создаю поток
Код:
...
CbbbDlg* lpMyObject = new CbbbDlg;
AfxBeginThread(MyFunction, lpMyObject,0,0,0,0);
а в MyFunction-е
Код:
...
UINT MyFunction(LPVOID pParam);
 UINT MyFunction(LPVOID pParam)
{
   CbbbDlg* lpObject = (CbbbDlg*)pParam;
  // CSingleLock FirstLock(&(lpObject->m_Critic)) ; /// что то для синхронизации

   lpObject->OnBnClickedButtonWrite();  // в нем WriteFile

return 0;

}

а в
Код:
void CbbbDlg::OnBnClickedButtonWrite()
{
   out = 20;  /// например out = 20
     while(1)
       WriteFile(hCOM,(LPCVOID)&out,sizeof(out),&dw,&ovr);

}
и создаю кнопку для чтения из порта
Код:
void CbbbDlg::OnBnClickedButtonReadCom()   ///кнопка
{

ReadFile(hCOM , (LPVOID)&in , sizeof(in) , &dw , &ovr);
   m_edit_int = in;  /// m_edit_int это <edit control> где должен отображатся <in>
UpdateData(FALSE);
}
а в конце
Код:
void CbbbDlg::OnBnClickedButtonCancel()  /// Cancel
{
PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart
CloseHandle(hCOM);

OnOK();
}
не какой ошибки не дает а после запуска приложения когда нажимаю кнопку OnBnClickedButtonReadCom() в <edit control>-е ничего не изменяется , результат <0>
« Последнее редактирование: 29-03-2010 08:12 от Вад » Записан
vegor
Интересующийся

am
Offline Offline

« Ответ #6 : 29-03-2010 07:46 » 

УРА, получилась после двуx месяцев: спасибо большое за помошь<Алексей1153++>,<resource>,<RXL>,<lag> и всем  другим
<Алексей1153++> той книгой была книга Секунова "VC++.NET" самоучитель.
И ТАК оказывается, что проблема была в обьявлений порта . Сначало надо было обьявить <событье> об обязательности которого я нигде не встричал. Когда внедрял в прогу эти строки только тогда и получилось , и без какого либо создания, нового потока(но этим думаю тоже можно ):
ovr.hEvent = CreateEvent(
      NULL,
      FALSE,
      FALSE,
      NULL
   );
И упомяну, что надо обязательно для своей страxовки в ручную установить обьем информационного баита(по своему расчетному протоколу для обмена информаций),потому что сначало сделал DCB структуру по умолчанию(dcb.ByteSize = 8;) а оно на самом деле взял dcb.ByteSize = 7; и больше числа (pow(2,7)==128) 127 уже передавал неправильно.
И интересно то что на самом деле данные из передающего(приемного) буфера не теряются до поступления новой информации.В обшем структура такая
Код:
///hCOM = CreateFileA("COM1", GENERIC_READ |GENERIC_WRITE,  ///так давал проблемы
/// 0,NULL,OPEN_EXISTING,NULL,NULL);  ////chi linum
 
hCOM = CreateFileA("COM1", GENERIC_READ |GENERIC_WRITE,   ///sozdanie
0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
 PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart
DCB dcb;

bSuccess = GetCommState(hCOM,&dcb);

dcb.BaudRate = CBR_9600;    ////aragutyun@
dcb.ByteSize = 8;    ///informacion biteri qanak@ I/O bayteri mech
/*
dcb.DCBlength;    ///dcb -i erkarutyunn e bayterov
dcb.EofChar;     ///dannineri prcnel@ cuyc tvox simvol
dcb.ErrorChar = 0;   ////zuygutyan simvoli sxal lineln e cuyc talis
dcb.EvtChar;
dcb.fAbortOnError = 0;     ///ete ka sxal read/write -n kasecnum e
dcb.fBinary;           ///  <1>
dcb.fDsrSensitivity = 0;   ///DSR -i handep sarqi zgayunutyunn e stugum
dcb.fDtrControl;       ////DTR signalin xekavarelu rejim
dcb.fDummy2;           /// == <0> chi ogtagorcvum
dcb.fErrorChar;
dcb.fInX;          ///////talis e XON/XOFF xekavarum <xoffLim,xonLim simvolneri het >
dcb.fNull;       /// <o>-yakan bayt@ den e netum
dcb.fOutX;            ////talis e XON/XOFF xekavarum <xoffChar,xonChar simvolneri het >
dcb.fOutxCtsFlow= 0;    ////miacnum e CTS-in hetevelu rejim@
dcb.fOutxDsrFlow;    ////miacnim e DSR.......
dcb.fParity = 0;         ////miacnum e bit chotnsti-n
dcb.fRtsControl ;     ///RTS -ic kaxvac patoki xekavarum e anum
//dcb.fTXContinueOnXoff = 1;   ////@ndunox buferi lcweluc , haxordman verchanaln e stugum
dcb.Parity = NOPARITY;          ///// kam=0 , kam=1
dcb.StopBits = ONESTOPBIT;        //// 0 , 1  ,2  == <1>bit    <1,5>bit   <2>bit
dcb.wReserved;     ////chi ogtagorcvum
dcb.wReserved1;   ////chi ogtagorcvum
dcb.XoffChar;   ///  XOFF simvoln e
dcb.XoffLim;    ////max -al simvolneri qanak@ @ndunox buferum XOFF-ic arach
dcb.XonChar;     ///  XONN simvoln e
dcb.XonLim;     ////min -al simvolneri qanak@ @ndunox buferum XON-ic arach

*/

SetCommState(hCOM,&dcb);

if(!SetCommState(hCOM,&dcb))
{
MessageBoxA(NULL,"не может установить конфигурацию","Заголовок потока",NULL);
}

bSuccess = SetCommMask(hCOM,
(DWORD)( EV_BREAK  |
EV_RXCHAR
));
if (!bSuccess) {
MessageBoxA(NULL,"SetCommMask -@ ustanowka chi exel","Заголовок потока",MB_OK);
return -1;
}

PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart

SetCommTimeouts(hCOM,&to);

//SetupComm(hCOM,1024,1024);  ///не обезательно в маленькиx буфераx

ovr.hEvent = CreateEvent(
NULL,
FALSE,
FALSE,
NULL
);

ovr.Internal = 0;
ovr.InternalHigh = 0;
ovr.Offset = 0 ;
ovr.OffsetHigh = 0 ;
//ovr.Pointer ;

PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart

а потом где то в OnBnClickedButtonwrite() ///write -е  (кнопка)

{
in = 0;
out = edit_write;

   BYTE* a = (BYTE*)(&out);  ////побаитовое передача/прием
   BYTE a0 = a[0];
   BYTE a1 = a[1];
   BYTE a2 = a[2];
   BYTE a3 = a[3];
//WriteFile(hCOM,(LPCVOID)&out,sizeof(out),&dw,&ovr);  /// можно и так
 //Sleep(80);                                             /// можно и так
//ReadFile(hCOM , (LPVOID)&in , sizeof(in) , &dw , &ovr);   /// можно и так
   
   BYTE* b = (BYTE*)(&in);  ////побаитовое передача/прием
   BYTE b0 = b[0];
   BYTE b1 = b[1];
   BYTE b2 = b[2];
   BYTE b3 = b[3];

   for(int i=0 ; i<4 ; i++)
   {
      WriteFile(hCOM,(LPCVOID)&a[i],sizeof(a[i]),&dw,&ovr);

//out = 0;
    Sleep(80);

ReadFile(hCOM , (LPVOID)&b[i] , sizeof(b[i]) , &dw , &ovr);

   }
  ///// ptr_in  это указатель (&ptr_in) 
   ptr_in = (int*)&b[0];
   in = *ptr_in ;
 
    edit_int = in;
UpdateData(FALSE);

  PurgeComm(hCOM,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); ///restart

 edit_write = 0;
  UpdateData(FALSE);

}
теперь один косметический момент: В передаюшем <edit box> -е когда все числа стираю
передоется сообшение "Enter an Integer" Как? нзбежать этого . Использовал событье EN_CHENGE:
void CMy200310Dlg::OnEnChangeEditWrite()
{     UpdateData(TRUE);   }

и просил бы если сможете подскажите как? можно например BMP фаил разделить на баиты, потом каким то своим законом кодировать и отправить ... потом получатель смог бы тем же самым законом преобразовать в BMP фаил, чтоб другие смогли взять и смотреть картинку.
СНОВА СПОСИБО за ПОМОЩ. Пусть БОГ благославит вас всеx.
« Последнее редактирование: 29-03-2010 07:58 от Алексей1153++ » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 29-03-2010 08:03 » 

Цитата
упомяну, что надо обязательно для своей страxовки в ручную установить

вообще-то, инициализировать структуру DCB удобно при помощи GetCommState, а потом поверх расставить свои поправки Улыбаюсь

Как передать файл (вообще любой файл)  -  открываешь файл (CreateFile) , делаешь с массивом байтов что нужно, передаёшь какими нужно кусочками. На том конце всё в обратном порядке делаешь - и файл передан

Цитата
Использовал событье EN_CHENGE:
а ты не используй событие - бери данные из окошка тогда, когда жмут на кнопку
Записан

vegor
Интересующийся

am
Offline Offline

« Ответ #8 : 08-04-2010 12:24 » new

какым способом  можно в рабочем потоке написать функций которые не я создал , например UpdateData() , Sleep(50) , ReadFile(),... У меня задает ошибки ,почему так получается ,может кто небуть обьяснить? , так должно и быть?.
И это для того чтобы во время приема - передачи данных главный поток не был занят этим...
Записан
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 08-04-2010 13:10 » 

Попытаюсь догадаться: проблема с синхронизацией потоков. Если это так - читай теорию про многопоточную синхронизацию (события, семафоры, мьютексы, ...)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines