Problem mit Threadkommunikation
-
Schreibe im Moment eine Konsolenanwendung.
Hab dabei das Problem das ich den Fenstertitel abhänig vom Fensterzustand verändern will (im Normalen und Maximierten Zustand wird Programmtitel angezeigt im Minimierten Zustand die Anzahl der verarbeiteten Dateien und Verzeichnisse).Da in einer Konsolenanwendung die Befehle nicht Ereignisorientiert sondern Schritt für Schritt nacheinander abgearbeitet werden bin ich auf die Idee eines Observer Threads gekommen.
Nun hab ich aber ein Problem beim Datenaustausch zwischen den Threads.
Nehme ich eine Pipe und frage sie mit read ab wartet er bis eine Nachricht in der Pipe ist bevor der Thread seine Bearbeitung fortsetzt.
Er soll aber prüfen ob was drin ist, und wenn nicht einfach mit den alten Werten weitermachen.Ein bisserl kompliziert daher der Quellcode:
Main Programm Headerenum PIPES {READ, WRITE}; struct SActionCount { int NumberofFiles; int NumberofDirectorys; int Pipes[2]; };Main Programm
SActionCount ActionCount; ActionCount.NumberofFiles = 0; ActionCount.NumberofDirectorys = 0; if(_pipe(ActionCount.Pipes, sizeof(ActionCount), O_BINARY | O_NOINHERIT ) != STANDART_ERROR) { write(ActionCount.Pipes[WRITE], &ActionCount, sizeof(ActionCount)); hWindowThread = Thread_Start_Window_Observer(&ActionCount.Pipes[READ], &ActionCount.WindowThreadID); } .... ActionCount.NumberofFiles++; write(ActionCount.Pipes[WRITE], &ActionCount, sizeof(ActionCount)); ... hWindowThread = Thread_Stop_Window_Observer(hWindowThread);Unterprogramm:
DWORD WINAPI Thread_Window_Observer(LPVOID lpParam) { HWND console_handle = GetConsoleWindow(); WINDOWPLACEMENT wndplacement; int PipeReadDeskriptor = *(int*)lpParam; while (true) { Sleep(CHECK_WINDOW_WAIT * 100); GetWindowPlacement(console_handle, &wndplacement); if(wndplacement.showCmd == SW_SHOWMAXIMIZED) { CString t_files; CString t_directorys; CString t_windowtitle; SActionCount ActionCount; read(PipeReadDeskriptor, &ActionCount, sizeof(ActionCount)); t_files.Format(_T("%i"), ActionCount.NumberofFiles); t_directorys.Format(_T("%i"), ActionCount.NumberofDirectorys); t_windowtitle = t_files + " Dateien, " + t_directorys + " Verzeichnisse bearbeitet."; console_SetWindowTitle(t_windowtitle); } if(wndplacement.showCmd == SW_SHOWNORMAL) { console_SetWindowTitle(WINDOW_TITLE); } } return STANDART_OK; } HANDLE Thread_Start_Window_Observer(int* PipeReadDesktipor) { DWORD dwThreadId; HANDLE hWindowThread; hWindowThread = CreateThread(NULL, 0, Thread_Window_Observer, PipeReadDesktipor, 0, &dwThreadId); SetThreadPriority(hWindowThread, THREAD_PRIORITY_BELOW_NORMAL); return hWindowThread; } HANDLE Thread_Stop_Window_Observer(HANDLE hWindowThread) { TerminateThread(hWindowThread, 0); CloseHandle(hWindowThread); hWindowThread = NULL; return hWindowThread; }
-
CreateNamedPipe - parameter 3.
Da gibts ein PIPE_WAIT falg. Dann bleibt ReadFile so lange stehen bis was da ist.
-
du könntest auch Events verwenden und nur aus der Pipe lesen wenn das Event gesetzt wurde
-
Das Problem ist aber das er genau nicht warten soll...
-
Wie geht denn das mit den Events ?
Ein kleiner Codeschnippsel würde mir schon ungemein weiterhelfen.
-
Du machst am besten in deinem Prog ein CreateEvent() und in deinem Thread ein OpenEvent(). Wichtig ist, dass bei beiden der gleiche Name angegeben wird.
In deinem Prog kannst du das Event dann mit SetEvent() setzen
In deinem Thread fragst du mit WaitForSingleObject(Handle auf Event, Zeit in ms) ob das Event gesetzt wurde
DWORD dwRet; dwRet = WaitForSingleObject(hEvent, 200); if (dwRet == WAIT_OBJECT_0) { // das Event wurde gesetzt // read (...); } else if (dwRet == WAIT_TIMEOUT) { // mach halt was anderes }
-
MasterGandi schrieb:
Das Problem ist aber das er genau nicht warten soll...
dann nimm das PIPE_NOWAIT flag
-
ein einfaches 'bool' reicht aus...
#define _WIN32_WINNT 0x5001 #include <windows.h> bool flag = false; char *text; void NewText (char *txt) { text = txt; flag = true; while (flag == true) Sleep(100); } void Thread (void *p) { HWND hwnd = GetConsoleWindow(); while (true) { Sleep(100); if (flag) { SetWindowText (hwnd, text); flag = false; } } } int main() { DWORD tid; CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)Thread, NULL, 0, &tid); while (1) { NewText ("Hallo"); Sleep (1000); NewText ("Doof"); Sleep (1000); } }man beachte die titelzeile