Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[204.236.220.47] |
|
Сообщ.
#1
,
|
|
|
Здравствуйте!
Есть следующая задача: написать многопоточное консольное приложение (использовать WinAPI), которое создаёт основной поток, тот в свою очередь создаёт несколько “подчиненных” потоков. Необходимо наладить обмен сообщениями между основным и подчинёнными потоками. Например, при получении сообщения от основного потока, подчинённые начинают построчно читать указанный текстовый файл и передавать сообщением в основной поток. Основной поток выводит строки из файла на экран. Написал следующий код: #include <stdio.h> #include <conio.h> #include <iostream> #include <fstream> #include <string> #include <sstream> #include <Windows.h> using namespace std; //Messages: #define WM_READ_FILE WM_APP+1 #define WM_SEND_LINE WM_APP+3 #define WM_EOF WM_APP+4 DWORD WINAPI SlaveThreadFunc(LPVOID lpParam) { DWORD MainThreadID=DWORD(lpParam); WPARAM CurrentID=(WPARAM)GetCurrentThreadId(); MSG msg; bool fDone=false; while (!fDone) { //do something //... while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { Sleep(100); switch (msg.message) { case WM_READ_FILE: { stringstream stream; stream << (char*)msg.lParam; string file_path = stream.str(); ifstream file(file_path); if(file.is_open()) { string line; while(getline(file, line)) { //Sleep(10); PostThreadMessage(MainThreadID, WM_SEND_LINE, CurrentID, (LPARAM)(line.c_str())); } file.close(); PostThreadMessage(MainThreadID, WM_EOF, CurrentID, 0); } break; } case WM_QUIT: { fDone=true; break; } } } } return 0; } DWORD WINAPI MainThreadFunc(LPVOID lpParam) { const int ThreadsCount=3; HANDLE SlaveThread[ThreadsCount]; DWORD SlaveThreadID[ThreadsCount]; MSG msg; int fDone=0; cout<<"Main thread was run."<<endl; for(int i=0; i<ThreadsCount; i++) { // Create the main thread SlaveThread[i] = CreateThread( NULL, // default security attributes 0, // use default stack size SlaveThreadFunc, // thread function name (void*)GetCurrentThreadId(), // argument to thread function (CurrentThreadId) 0, // use default creation flags &SlaveThreadID[i]); // returns the thread identifier if (SlaveThread[i] == NULL) ExitProcess(3); else cout<<"Slave thread " << SlaveThreadID[i] << " was run."<<endl; } Sleep(100); PostThreadMessage(SlaveThreadID[0], WM_READ_FILE, 0, (LPARAM)"file0.txt"); PostThreadMessage(SlaveThreadID[1], WM_READ_FILE, 0, (LPARAM)"file1.txt"); PostThreadMessage(SlaveThreadID[2], WM_READ_FILE, 0, (LPARAM)"file2.txt"); while (fDone < ThreadsCount) // lengthy operation { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { switch(msg.message) { case WM_SEND_LINE: { cout << "Thread " << DWORD(msg.wParam) << ": " << (char*)msg.lParam << endl; break; } case WM_EOF: { PostThreadMessage(DWORD(msg.wParam), WM_QUIT, 0, 0); fDone++; break; } } } } // Wait until all slave threads have terminated. WaitForMultipleObjects(ThreadsCount, SlaveThread, TRUE, INFINITE); // Close all thread handles and free memory allocations. for(int i=0; i<ThreadsCount; i++) { CloseHandle(SlaveThread[i]); } return 0; } void main() { HANDLE MainThread; DWORD MainThreadID; // Create the main thread MainThread = CreateThread( NULL, // default security attributes 0, // use default stack size MainThreadFunc, // thread function name (void*)GetCurrentThreadId(), // argument to thread function (CurrentThreadId) 0, // use default creation flags &MainThreadID); // returns the thread identifier // Check the return value for success. If CreateThread fails, terminate execution. if (MainThread == NULL) ExitProcess(3); // Wait until main thread has terminated. WaitForSingleObject(MainThread, INFINITE); // Close main thread handle CloseHandle(MainThread); cout<<"Press any key for exit..."; _getch(); } Проблема в том, что обмен сообщениями идёт, а строки с текстом от подчинённых потоков "теряются", (char*)msg.lParam - пустой. case WM_SEND_LINE: { cout<<"Thread "<< DWORD(msg.wParam)<<": "<<(char*)msg.lParam<<endl; break; } Если установить небольшую задержку Sleep(10); в цикле while(getline(file, line)){…}, то часть строк начинает доходить. См. скриншоты... Помогите понять в чём проблема? Прикреплённая картинка
Прикреплённая картинка
|
Сообщ.
#2
,
|
|
|
>string line;
>... >PostThreadMessage(MainThreadID, WM_SEND_LINE, CurrentID, (LPARAM)(line.c_str())); line - указатель, адрес. Послали адрес сообщением, оно встало в очередь. За это время прочитана новая строка или несколько, память под line при этом перераспределилась, и по отосланному адресу уже никто не живёт. Сообщение наконец пришло в главный поток. Он глядь - а по тому адресу мусор. простые варианты решения - выделять каждый раз новую строку, а старую пусть освобождает главный поток. - создать единую потокобезопасную очередь, в которую потоки складывают строки, а главный ее разгребает |
Сообщ.
#3
,
|
|
|
Цитата MBo @ Спасибо за подсказку! Думаю проблема решена... |