Häufige Gui-Updates lassen GUI abstürzen
-
Hallo Leute,
ich brauche mal wieder die Hilfe von Leuten, die mehr Ahnung von der Materie haben, als ich.
Ich habe ein Programm, bei dem von einer Hardware in sehr umfangreichen Maße Daten ausgelesen und teilweise live verarbeitet werden. Hierfür laufen viele Threads, wodurch der gesamte PC relativ an seinen Leistungsgrenzen ist, aber es funktioniert.
Nur manchmal kommt nach einiger Zeit der Messung der Zeitpunkt, dass die GUI nicht mehr aktualisiert wird oder werden kann, was nicht nur mein Programm, sondern ganz Windows betrifft.
Ich lasse in einem kleinen Fenster gewisse Messwerte zur Kontrolle ständig aktualisieren und neuerdings auch farblich hervorheben. Zudem blink ein Button, der anzeigt, welcher Mess-Modus gerade aktiv ist. Ich habe subjektiv das Gefühl, dass diese neuen Hervorhebungen für die deutlich schwächere GUI-Leistung ist und ich gehe davon aus, dass ich vielleicht irgendwie Speicher nicht mehr freigebe, wodurch der schon sehr beanspruchte RAM irgendwann Probleme macht.
Hiermit lasse ich den Button blinken, die Funktion wird halbsekündlich von einem Timer, der auch andere Aufgaben übernimmt, angestoßen:
void Klasse::SetSelectedMode(int iIDC) { InvalidateRect (GetDlgItem(m_hwndDialogInfo, iRecentButtonIDC), NULL, TRUE); UpdateWindow(GetDlgItem(m_hwndDialogInfo, iRecentButtonIDC)); iRecentButtonIDC = iIDC; HWND hStatusText = GetDlgItem(m_hwndDialogInfo, iIDC); RECT rect; if(hStatusText != NULL) { HDC hDC = GetWindowDC(hStatusText); GetClientRect(hStatusText, &rect); HPEN hPen; if(!bActiveButtonSelected || !m_bMeasLoopThreadRunning) { hPen = CreatePen(PS_SOLID, 4 , RGB(0,205,0)); bActiveButtonSelected = true; } else { hPen = CreatePen(PS_SOLID, 4 , ::GetSysColor(COLOR_BTNFACE)); bActiveButtonSelected = false; } SetTextColor(hDC, RGB(0,0,255)); // SetBkMode(hDC,TRANSPARENT); PAINTSTRUCT ps; BeginPaint(hStatusText, &ps); SelectObject(hDC, hPen); MoveToEx(hDC,rect.top+1, rect.left+1, NULL); LineTo(hDC,rect.right-1, rect.top+1); LineTo(hDC,rect.right-1, rect.bottom-1); LineTo(hDC,rect.left+1, rect.bottom-1); LineTo(hDC,rect.left+1, rect.top); DeleteObject(hPen); EndPaint(hStatusText, &ps); } }Hiermit färbe ich die Messergebnisse ein (Auszug):
BOOL CALLBACK DialogProcMeasInfo(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { ... switch(uMsg) { case WM_CTLCOLORSTATIC: { if(GetDlgItem(hwndDlg, IDC_STATIC_NUM_VALID_PHOTONS) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_INVALID_PHOTONS) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_PHOTONFRAME_OFFSET) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_RECEIVED_PHOTONFRAMES) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_TRANSFER_DURATION) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_FIFO_USAGE) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_DROPPED_PHOTONFRAMES) == (HWND)lParam) { SetTextColor((HDC) wParam,RGB(0,0,255)); SetBkColor((HDC) wParam,GetSysColor(COLOR_BTNFACE)); return (int)CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); } else if(GetDlgItem(hwndDlg, IDC_STATIC_NUM_VALID_PHOTONS2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_INVALID_PHOTONS2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_PHOTONFRAME_OFFSET2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_RECEIVED_PHOTONFRAMES2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_TRANSFER_DURATION2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_FIFO_USAGE2) == (HWND)lParam || GetDlgItem(hwndDlg, IDC_STATIC_NUM_DROPPED_PHOTONFRAMES2) == (HWND)lParam) { SetTextColor((HDC) wParam,RGB(245,0,0)); SetBkColor((HDC) wParam,GetSysColor(COLOR_BTNFACE)); return (int)CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); } return 0; } } }Bin ich irgendwo zu sehr ressourcenverschwendent oder habe ich etwas vergessen? Was kann ich besser machen?
Vielen Dank für eure Hilfe,
Jonson
-
Du kannst ja mal im Taskmanager die Spalte "GDI-Handles" einblenden und die Anzahl deines Prozesses beobachten.
Was auffällt:HDC hDC = GetWindowDC(hStatusText); // ReleaseDC fehltIrgendwann ist die maximale Anzahl an Handles erreicht und es läuft eben nix mehr.
Das Ganze schreit natürlich geradezu nach RAII, damit solche Fehler nicht wieder auftreten.
-
Wann aktualisierst du denn dein GUI? Mit jedem neuen Messwert?