logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak uniknąć zamrażania okna głównego przy uruchamianiu procesu wtórnego w C++?

Janek-Kam 25 Gru 2018 23:19 912 12
REKLAMA
  • #1 17651123
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Witam

    Co zrobić, żeby po uruchomieniu procesu wtórnego, z okna głównego programu, program ten się nie zawiesza (zamrażał) ?

    W niżej zamieszczonym programie jest tworzony nowy proces (CreateProcess), a w nim uruchamiany jest program exe – np. calc.exe.
    Po uruchomieniu exe okno głównego procesu się zawiesza. Nie odświeża się treść z okna.
    Wystarczy inne okno przesunąć nad głównym oknem programu i wszystko znika.
    Zawieszanie następuje po uruchomieniu WaitForSingleObject.
    Po zakończeniu nowego procesu ma być coś wypisane w oknie.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Pozdrawiam
    Janek
  • REKLAMA
  • #2 17652872
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    WaitForSingleObject właśnie ma zawieszać... Czeka na zamknięcie procesu. Jak nie potrzebujesz kodu zwrotu to po prostu olej. Jak potrzebuejsz możesz albo zrobić pętlę, w której bedziesz obsługiwał komunikaty, albo uruchomić z osobnego wątku.
  • REKLAMA
  • #3 17654175
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Dziękuję bardzo.
    Potrzebuję informacji, że program zewnętrzny (exe) zakończył się.

    Myślałem o komunikatach, tylko jeszcze nie wiem jaki to będzie komunikat, który się pojawi gdy proces uruchamiający EXE się zakończy, aby to obsłużyć w switch(Message).
    Nad wątkiem też się zastanawiałem, ale tu też by chyba było potrzebne obsłużenie komunikatu (nie wiem jakiego), który się pojawi po zakończeniu wątku.
    W wątku pewnie też musiałby być uruchomiony proces (CreateProcess), czyli to samo co wcześniej.
  • #4 17655471
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    W wątku uruchamiasz program, robisz WaitFor..., po odebraniu wiesz, że proces się zakończył, możesz poinformować wątek główny (np. wiadomością). To, że wątek będzie zawieszony w ogóle nie jest istotne. Jak koniecznie chcesz jego responsywność (np. możliwość zamknięcia przed zakończeniem procesu) to dajesz krótki timeout i pętla.
  • #5 17656586
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Dziękuję bardzo.
    Czy takie rozwiązanie jest dobre – jak w kodzie poniżej?
    Czy jest jakieś niebezpieczeństwo, że jakiś inny komunikat z systemu albo innej aplikacji mi coś popsuje?

    Jak przekazać uchwyt okna jako parametr w procedurze TrescWatku()?
    Jak podaję TrescWatku(HWND UchwytOkna) to wychodzi błąd.

    Nie wiem też, dlaczego WaitForSingleObject dla wątku nie zwraca 0 (zera).

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 17658345
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Odradzałbym pokazywanie komunikatów z wątku. Wyślij wiadomość niezależnie od rezultatu, ale ten rezultat przekaż w wiadomości. Nie musisz wtedy też ekstra obsługiwać kodu końca wątku.

    A tak generalnie nie programuję w C i wieki nie miałem styczności z tak gołym WinAPI, więc trudno mi ocenić całość :)
  • REKLAMA
  • #7 17658384
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Dziękuję bardzo.
    Komunikaty przesyła się przez SendMessage, a wiadomości jak?
    Rozumiem, że "przekazywanie komunikatów" jest czymś innym niż "wysyłanie/przekazywanie wiadomości".
  • REKLAMA
  • #9 17658649
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Aha, no tak. Nie potrzebuję.
    Ale i tak PostMessage muszę użyć w funkcji obsługującej wątek, żeby przekazać informację do głównego okna, że się zakończył proces uruchomiony w wątku.

    Kodu końca wątku rzeczywiście nie muszę obsługiwać, ale tak z ciekawości chciałbym wiedzieć.
    Dlaczego funkcja WaitForSingleObject wywołana w sekcji związanej z komunikatem WM_COMMAND, zwraca 0 (zero) po zakończeniu wątku, albo 258 – gdy jest przekroczony czas oczekiwania, a wywołana w sekcji związanej z komunikatem WM_USER+1 zwraca –1?
    W obu przypadkach w tej funkcji podawany jest uchwyt do tego samego wątku.
  • #10 17658816
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Ja widzę tylko w jednym przypadku sprawdzasz wartość zwracaną przez WaitforSingleObject. Natomiast generalnie w obsłudze wiadomości sprawdzasz uchwyt wątku, który może już nie istnieć w tym momencie. Stąd rezultat WAIT_FAILED. Zobacz, co robi _endthread https://docs.microsoft.com/en-us/cpp/c-runtim.../reference/endthread-endthreadex?view=vs-2017
  • #11 17659161
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    Tak, w przypadku wątku z uchwytem hThread tylko raz sprawdzam w bloku dla komunikatu WM_USER+1.
    Ale gdy używałem tej funkcji przy oczekiwaniu na zakończenie procesu (przypadek w pierwszym poście) to z dłuższym czasem – np. 5000 - WaitForSingleObject( hThread,5000), albo z parametrem INFINITE, kody zakończenia miał wartość albo 258 – czyli przekroczenie czasu oczekiwania, albo 0 gdy zakończy się wątek.
    To w przypadku gdy zmodyfikowałem trochę obsługę i było
    KodWyjscia=WaitForSingleObject( ProcInfo.hProcess, 5000 )
    albo
    KodWyjscia=WaitForSingleObject( ProcInfo.hProcess, INFINITE )

    Rzeczywiście, ta funkcja kończąca wątek zamyka uchwyt wątku. Czyli może faktycznie to jest równoznaczne z usunięciem tego uchwytu i nic się już nie można dowiedzieć o wątku.
    Teraz sprawdziłem to i faktycznie zawiesza się program.
    Czyli taka obsługa odpada.
    Dziękuję bardzo za wskazówki i pomoc.

    Dodano po 24 [minuty]:

    Dodałem drugi przycisk i zmieniłem kod.
    Sprawdziłem, że nawet jeżeli wątek jeszcze jest i sprawdzam w obsłudze komunikatów KodWait=WaitForSingleObject to zawsze wartość jest -1. Dziwne.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #12 17659689
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Bo musiałbyś przejść najlepiej na CreateThread i CloseHandle wywoływane poza wątkiem. Jak będziesz korzystać z tych _beginthread i _endthread w wątku, to nie możesz liczyć na to, że uchwyt do niego poza nim będzie istnieć w danej chwili.
  • #13 17659951
    Janek-Kam
    Poziom 9  
    Posty: 134
    Pomógł: 3
    Ocena: 7
    _beginthread jest poza wątkiem, w programie głównym, i tam jest odczytywany uchwyt.
    Wybrałem te funkcja zamiast CreateThread, bo w kursie
    napisali "że w praktyce prawie nikt nie używa tej funkcji" i że może powodować problemy.
    Ale spróbuję użyć tych CreateThread i CloseHandle.
    Dziękuję bardzo.

Podsumowanie tematu

✨ W dyskusji poruszono problem zamrażania okna głównego aplikacji C++ po uruchomieniu procesu wtórnego za pomocą funkcji CreateProcess. Użytkownik zauważył, że program zawiesza się podczas oczekiwania na zakończenie nowego procesu, co prowadzi do braku odświeżania interfejsu. Odpowiedzi sugerują, aby zamiast używać WaitForSingleObject w głównym wątku, uruchomić nowy proces w osobnym wątku, co pozwoli na obsługę komunikatów i uniknięcie zamrażania. Użytkownicy podkreślają znaczenie przesyłania komunikatów między wątkami oraz korzystania z funkcji PostMessage do informowania głównego okna o zakończeniu procesu. Wskazano również na potencjalne problemy związane z używaniem funkcji _beginthread i _endthread, sugerując przejście na CreateThread i odpowiednie zarządzanie uchwytami.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA