Od pewnego czasu zainteresowała mnie pewna sprawa. Przez całe lata po prostu przyjmowałem do wiadomości, ze tak jest i nie drążyłem tematu, ale teraz nie rozumiem, dlaczego tak jest.
Załóżmy, że napiszę dwa takie same programy, jeden konsolowy, drugi w okienkach, oba programy będą w C# dla .NET. Nie zmienia to faktu, że w tej sprawie nie ma żadnego znaczenia, w jakim języku i w jakiej technologii pisze program.
Pierwszy program to program tekstowy w konsoli. Program czeka na naciśnięcie klawisza Enter, a potem wypisuje liczby od 1 do 10 w odstępach jednej sekundy. Uruchamiam program, naciskam Enter i przez 10 sekund, co sekundę pojawia się kolejna liczba, nie ma żadnej filozofii. Odmierzenie jednej sekundy wygeneruję za pomocą pustej pętli, która porównuje wskazanie zegara ze wskazaniem w chwili rozpoczęcia. Akurat w C# jest klasa Stopwatch, która ułatwia odmierzanie czasu. Oczywiście, że można skorzystać z Thread.Sleep
, ale w tym przypadku chciałem zasymulować jakieś obciążające czynności.
Drugi program ma formatkę, która zawiera jedno pole tekstowe i jeden przycisk. W tym programie, do kliknięcia przycisku podłączam funkcję, która czyści pole tekstowe i dopisuje do pola kolejne liczby. Uruchamiam program, klikam przycisk i niespodzianka (ja teraz dobrze wiem, co się zdarzy, ale jak wieki temu zaczynałem przygodę z okienkami, to tego się nie spodziewałem). Program zupełnie zawiesi się, w menedżerze zadań przedstawiony jako "nie odpowiada", a dopiero po 10 sekundach odwiesi się i momentalnie wypisze wszystkie liczby.
Aby uzyskać oczekiwany efekt, to przerabiam program tak, żeby uruchamiał dodatkowy wątek i w tym wątku uruchomił wypisywanie liczb, jednak samo wypisanie też jest utrudnione, bo akurat w C# trzeba to robić poprzez wywołanie Invoke
i obiekt delegate
(dokładnie nie pamiętam, bo dawno tego nie robiłem).
Pytanie jest proste. Jak to jest, że robię dwa identyczne programy, różniące się tylko interfejsem (tekstowy i okienkowy), a w interfejsie tekstowym nic się nie wiesza, każde wypisanie pokazuje się natychmiast, a w okienkach, to uruchomienie funkcji zawiesza program aż do czasu zakończenia? Z czego wynika, że w przypadku, gdy w okienkach chce się coś wypisać, zmienić z dodatkowego wątku, to trzeba robić obejścia, a w programie tekstowym, niezależnie od tego, skąd wywoła się Console.Write()
, to bez żadnego problemu tekst będzie wypisany?
Przerabiałem Lazarus, Winforms, GTK#, Qt, GTK+, Swing i w każdym przypadku, uruchomienie funkcji bez tworzenia dodatkowego wątku zawiesza program. Dlaczego to nie działa tak samo, jak w interfejsie tekstowym?