Hello.

He broke his head thinking that he was wrong and came to the conclusion that in general everything is wrong, there are suspicions that it is impossible to do this.
The essence of the program is that one stream performs calculations, creates a channel and gives the result to another stream, which, after transformations, displays the data on the screen.

Here is the main function, everything is clear. We create two streams, nothing goes to their input.

int _tmain(int argc, _TCHAR* argv[]) { DWORD dw; HANDLE IDThread[2]; IDThread[0]=CreateThread(NULL,0,MainTread,0, 0, &dw); IDThread[1]=CreateThread(NULL,0,MinorThread,0, 0, &dw); WaitForMultipleObjects(ThrCount,IDThread,TRUE,INFINITE); system("pause>>void"); return 0; } 

Next, the 1st thread. (I simplified the program to horror, leaving the most basic).

 DWORD WINAPI MainTread(LPVOID Insert) { wchar_t *PName = L"\\\\.\\pipe\\TransmitPipe"; //Имя канала HANDLE hPipe; //Экземпляр самого канала BOOL Success; //Принимает значения возвращаемые функциями DWORD byteCnt, byteWrt; //Число байт которые надо записать в поток и счетчик байт реально записанных в канал. char X[10]; //Будем передавать второму потоку этот чар for(int i=0; i<10; i++) {X[i]='9';} //Заполним его девятками X[i]='\0' //На всякий случай //Самое интересное hPipe = CreateNamedPipe(PName, PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,PIPE_UNLIMITED_INSTANCES,4096,4096,0,NULL); if(hPipe!=INVALID_HANDLE_VALUE) {std::cout<<"1) Pipe create is OK \n";} //Проверка. Если экземпляр не вернул неправильное значение значит канал создан. 1) - означает что поток 1ый. Success = ConnectNamedPipe(hPipe, NULL); //Ожидаем запроса на соединение с этим каналом if(Success){std::cout<<"1) Connect is OK \n";} //Если результат 1, значит соединение прошло Success = WriteFile(hPipe, X, byteCnt, &byteWrt, NULL); //Пишем наш Х в канал hPipe if(Success){std::cout<<"1) Write is OK \n";} //Функция вернула 1 - все ОК } 

Next, the second stream (There in the output messages on the screen will be "2)").

 DWORD WINAPI MinorThread(LPVOID Insert) { wchar_t *PName = L"\\\\.\\pipe\\TransmitPipe"; //Все так же, это имя канала HANDLE hPipe; //Экземпляр BOOL Success; DWORD pMode; //Это указатель на режим работы, подробнее ниже. char X[10]; //Сюда пишем, то что пришлет канал hPipe = CreateFile(PName,GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); //Подключение к существующему каналу (созданному в 1ом потоке) if(hPipe!=INVALID_HANDLE_VALUE) {std::cout<<"2) File create is OK \n";} //Проверка (тот же смысл что и в 1П) Success = WaitNamedPipe(PName, NMPWAIT_WAIT_FOREVER); //Ожидание подключения к экземпляру канала if(Success){std::cout<<"2) Pipe avelible OK \n";} //Канал доступен если все нормально pMode = PIPE_READMODE_MESSAGE; //Режим чтения сообщений Success = SetNamedPipeHandleState(hPipe, &pMode, NULL, NULL); //Переключение канала в режим чтения сообщений if(Success){std::cout<<"2) Readmode is OK \n";} Success = ReadFile(hPipe, Х, 4096, &byteWrt, NULL); //Чтение из экземпляра в Х. 4096 - размер буфера под читаемое сообщение if(Success){std::cout<<"2) Read is OK \n";} std::cout<<X; } 

Displays 0.

But he writes:

alt text

That is, the channel is created and data is written there, and even the second stream is connected to it, in general, everything stops working.

So the question: Was it a good idea to throw a channel from stream to stream? Maybe you know where I nakosyachil code?


Put semaphores. The second stream is trying to read from the channel: alt text

The essence of the error: MSDN

 ERROR_NOACCESS 998 (0x3E6) Invalid access to memory location. 

Question: Why? Writing to the channel is normal, why is there an error when reading, and yes even with a complaint about a section of memory.

  • @alexlz I can't comment on the answer = (Thanks, now it's clear why there is a problem with memory) - BlackOverlord

1 answer 1

Using pipes for data transfer within a single process is the wildest overkill, it would be worse to use sockets.

To transfer data from a stream to a stream, use a shared data structure (for example, std :: queue), protecting it from simultaneous access using a mutex (for example, CRITICAL_SECTION, if you want Windows-specific, or better std :: mutex , if your compiler supports standard C ++ 11).

You really need a Producer-Consumer pattern.

Welcome to the multi-threaded programming universe!


Regarding your code - maybe the reading thread is waiting for 4096 bytes of data to be finally put into the pipe? Try to read one byte as a debug.

  • Thank you) I thought so, looking at how sad the result was, but alas, this program was not my idea ... - BlackOverlord
  • @BlackOverlord: look at the update of the answer, so about the pipes - VladD
  • I read about semaphores, I'll try) - BlackOverlord
  • @BlackOverlord: oh! semaphores megarulosis! although I would use the condition variable. - VladD
  • 2
    Well, the question is not in the MainThread installation byteCnt to write (apparently this has already been fixed). But the length of the buffer for reading lpNumberOfBytesToRead in the ReadFile should not be larger than the size of the buffer X itself (otherwise there may be memory problems) - alexlz