ListBox blockiert durch WaitForSingleObject



  • Hallo,
    meine Applikation erstellt 6 Threads mit der CreateThread Funktion in einer for schleife, diese laufen einmal und beenden sich dann.
    Soweit funktioniert das ganze, ich möchte nun nach dem Beenden eines jeden Threads eine Nachricht in einer ListBox oder einem Textfeld ausgeben, nachdem WaitForSingleObject das beenden des Threads signalisiert. Das funktioniert jedoch nicht, die Nchrichten (für alles 6 Threads) werden nach Beendigung der for schleife alle auf einmal angezeigt.

    struct ThreadData
    {
        HANDLE funktionsHandle;
        HANDLE hHandletoThread;
        int data;
        bool ftCheck;
        DWORD dwThreadId;    
    };
    
    void CProgramDlg::OnBnClickedsomebutton()
    {
        CString text
        for (int i = 0; i < 6; i++ ) 
        {							
            ThreadData* threadData = new ThreadData;
            threadData->data = i;
            threadData->ftCheck=false;	
    
            threadData->hHandletoThread = CreateThread(
                NULL,                     //default security attributes 
                0,                        //use default stack size  
                ThreadFunc,               //thread function 
                (void*)threadData,        //argument to thread function 
                0,                        //use default creation flags 
                &threadData->dwThreadId); //returns the thread identifier
    
            DWORD wait = WaitForSingleObject(threadData->hHandletoThread, 2000);
    
            if (wait == WAIT_OBJECT_0)
            {				
                text.Format("Thread %i ist beendet",i)
                OListBox.AddString(text);				
            }
            else if (wait == WAIT_TIMEOUT)
            {
                MessageBox("One Device failed to initialize/reset", "Error", MB_OK);		}
        }
    }
    

    Der Thread macht nichts anderes als ein delay hervorrufen durch hochzählen einer Variablen.
    Nun möchte ich das nach jeder Thread Beendigung eine Nachricht mit der Threadnummer in der ListBox ausgegeben wird. Funktioniert wie oben beschrieben leider nicht.

    Hat irgendwer Ideen woran dasliegen kann?

    WAIT_OBJECT_0 wird ausgeführt, das hab ich getestet indem ich dort eine Messagebox habe ausgeben lassen.

    MessageBox("Test", "Thread", MB_OK);
    

    Diese wurde mit der entsprechend der im Thread erstellten Zeitverzögerung ausgegeben. Und auch der Eintrag in die Listbox fand statt, ohne die MessageBox nicht. 😕

    vielen dank im vorraus
    dingo



  • Hoi!

    Öhm, bin mir nicht sicher, ob ich Dich richtig verstanden habe... :
    Du willst 6 Threads parallel zu Deinem Hauptthread ausführen, die jeweils -bei Beendigung- einen Text in eine ListBox ausgeben? Dafür brauch man aber keine Threads, wenn Du nur einen Delay in den Threads abzählen lässt; es reicht auch ein simpler Timer 😉 .

    Dingo3000 schrieb:

    ich möchte nun nach dem Beenden eines jeden Threads eine Nachricht in einer ListBox oder einem Textfeld ausgeben, nachdem WaitForSingleObject das beenden des Threads signalisiert

    WaitForSingleObject signalisiert *kein* Ende, sondern wartet nur, bis ein Thread endet (keine Ahnung, ob Du das meintest, hast es auf jeden Fall nicht geschrieben 🤡 ). Da WaitForSingleObject den aktuellen Thread blockiert (also den, in dem die Funktion aufgerufen wurde), versteh ich den Sinn Deines Vorhabens auch nocht janz^^: Du erstellst einen Thread und wartest, bis sich dieser wieder beendet hast - warum dann überhaupt der Thread ? 😕

    Du könntest die Ausgabe der ListBox-Textes auch in den Thread verlagern.

    Achte allerdings auf korrekte Aktions-Synchronisation.

    Hoffe ich konnte helfen 😉 !

    PS: Gibst Du die dynamisch allokierten ThreadData-Objekte auch wieder frei 😋 ?



  • CodeFinder schrieb:

    Öhm, bin mir nicht sicher, ob ich Dich richtig verstanden habe... :
    Du willst 6 Threads parallel zu Deinem Hauptthread ausführen, die jeweils -bei Beendigung- einen Text in eine ListBox ausgeben? Dafür brauch man aber keine Threads, wenn Du nur einen Delay in den Threads abzählen lässt; es reicht auch ein simpler Timer 😉 .

    Ok, das war vielleicht etwas zu reduziert ausgedrückt ^^
    In den 6 Threads kommuniziere ich mit 6 USB UART Controllern via virtuellem Comport. Wollte das nicht alles in den code mit packen, weil ich denke das das uninteressant für die Problemstellung ist, da es ja funktioniert. Dazwischen befindet sich besagter Delaytimer auf den ich die Funktion hier reduzierte.

    Naja "signalisiert" ist doch so falsch nicht, das Handle auf das ich warte "becomes signaled" also weiß ich der Thread ist zu Ende 🙂

    CodeFinder schrieb:

    Da WaitForSingleObject den aktuellen Thread blockiert (also den, in dem die Funktion aufgerufen wurde), versteh ich den Sinn Deines Vorhabens auch nocht janz^^: Du erstellst einen Thread und wartest, bis sich dieser wieder beendet hast - warum dann überhaupt der Thread ?

    Naje es blockiert doch solange bis der Thread beendet ist, danach sollte es halt eine ListBox Ausgabe geben, bevor die for schleife neu durchläuft um den nächsten Thread zu starten. Und genau dies funktioniert nicht, außer wenn eine MessageBox das ganze System anhält zwichendurch.
    Der Thread erfüllt wie oben beschrieben noch einge andere Funktionen.

    CodeFinder schrieb:

    Du könntest die Ausgabe der ListBox-Textes auch in den Thread verlagern.

    Achte allerdings auf korrekte Aktions-Synchronisation.

    Das wollte ich aus genau diesen Synchronisationsgründen wenn möglich vermeiden 😉 mit kein Threadmeister und musste mir das ganze so ein bisschen zusammenklauben.
    Deswegen läuft das ganz nun auch sequenziell, ich hätte es eigentlich gern parallel, das quasi alle 6 threads gleichzeitig ihr Zeugs machen und wenn alle fertig sind, ich eine Ausgabe in der besagten ListBox mache, aber ich bin an der WaitForMultipleObject Funktion gescheitert. Deswegen erstmal die WaitForSingleObject in einer Schleife.

    Am Ende eines jeden Threads geb ich den Speicher und die Handle wieder frei, wenn ich Morgen auf der Arbeit bin poste ich gern nochaml den Code dafür.

    Hoffe es damit ein bisschen klarer gemacht zu haben



  • Ich denke UpdateWindow sollte helfen


  • Mod

    1. Fenster sind threadafin. D.h. gehören immer zu dem Thread und der Message Queue in dem sie erzeugt wurden.
    2. Sendet ein Thread an ein Fenster eines anderen Threads eine Nachricht mit SendMessage, dann wird diese Nachricht nur ausgeliefert, wenn der andere Thread GetMessage/PeekMessage ausführt, denn diese Nachricht kommt in die Messagequeue.
    3. Steht Dein Hauptthread auf WaitForSingleObject, dann kann er keine Nachrichten empfangen weil er nämlich nicht GetMessage/PeekMessage ausführt.

    Die Folge: Der Mainthread wartet auf den Worker, der Worker will was an den Mainthread senden und beendet nicht.

    Das ganze geht deshalb wenn eine MessageBox angezeigt wird, weil dann eine Messageloop läuft.



  • mmmh, das erklärt so manches, wobei scheinbar keine Deadlock Situation eingetreten ist da der Hauptthread ja weiterläuft nachdem alle Workerthreads beendet sind.

    Wie sieht denn so eine synchronisation für z.B. 6 Threads aus wenn ich die alle parallel starte und der Hauptthread warten soll bis sie alle beendet sind?


  • Mod

    Klar wird Dein Deadlock aufgehoben, weil Du eben nicht INFINITE auf die Workerthreads wartest. Würdest Du INFINITE warten dann hättest Du den perfekten Deadlock! ⚠

    Ich verwende andere Mechanismen. Ich warte zum Beispiel niemals in meinem GUI-Thread mit einer Wait Zeit !=0!

    Es könnte so gehen:
    - 6 Threads starten.
    - Dialog oder Programm mit EnableWindow lahmlegen, damit keine Reentrancy entsteht.
    - Timer starten (alle 200msec).
    - Im Timer kontrollieren ob alle Threads durch sind (0 Wartezeit) Man kann WaitForMultipleObjects verwenden.
    - Wenn aller fertig sind, oder Timeout erreicht. (Gegebenefalls Threads terminieren). UI wieder enablen.


Anmelden zum Antworten