Programowanie wielo-UI-wątkowe

Możliwość tworzenia aplikacji wykorzystujących wątki robocze (ang. Worker Threads) w .NET to żadna nowość. Istnieje wiele dobrze udokumentowanych sposobów radzenia sobie z tak zdefiniowanym zagadnieniem wielowątkowości:
Threading in C# by Joseph Albahari

Jednakże prawie wszystkie dostępne w sieci artykuły poruszają (i opisują) zagadnienie wielowątkowości wyłącznie w kontekście wątków wykonujących żmudne (czyt. długie) obliczenia w tle bądź operacje wejścia/wyjścia o nieprzewidywalnym czasie ukończenia. Mówiąc inaczej, metody te opisują sytuacje, w których wątek główny programu (często ten, na którym funkcjonuje graficzny interfejs użytkownika) powołuje do życia wątki obliczeniowe po to, aby nie utracić responsywności (popularne "Brak odpowiedzi...") w trakcie wykonywania tychże obliczeń. Brak jest natomiast prostych odpowiedzi na pytania jak tworzyć i komunikować się pomiędzy dwoma, trzema itd. niezależnymi wątkami, które same pełnią rolę "wątków głównych" (ang. UI Threads

Handle Unhandled, czyli .NET'owa obsługa krytycznych błędów w kilku krokach

W programowaniu, jak w codziennym życiu, pojawiają się sytuacje całkiem nieprzewidziane. Sytuacje, czy też zdarzenia, na które nie mieliśmy gotowych odpowiedzi na etapie projektowania programu. Lecz człowiek to nie maszyna. O ile w prawdziwym świecie na każde nieprzewidziane zdarzenie mamy szansę choćby "jakoś", nawet prowizorycznie, zareagować (nie dotyczy tragicznych zdarzeń losowych skutkujących definitywnym wyjściem z nieskończonej pętli życia), to już prawie każde nieprzewidziane działanie algorytmów komputerowych zwykle kończy się dla użytkownika drastycznie.

Cóż wtedy czynić? Gdyby taka sytuacja miała miejsce na etapie przygotowywania aplikacji, programista z pewnością rozwiązałby problem. Jeśli natomiast błąd w oprogramowaniu uwidacznia się po stronie użytkownika końcowego - tu sprawa wygląda nieciekawie. Użytkownik po prostu coś wymamrocze pod nosem (zapewne przeklnie dzień, w którym zdecydował się na zakup Twojego programu :) i uruchomi aplikację ponownie. Do czasu następnego błędu, czyli powielenia schematu, który przyczynił się do powstania poprzedniego. I tak w kółko.

Zmiana paradygmatu, czyli o GUI słów kilka

Mały paradoks oprogramowania

Kiedykolwiek programista pragnie uszczęśliwić stałego użytkownika, oferuje mu bądź ulepszoną funkcjonalność produktu bądź nowy, "ulepszony" a zarazem urzekający interfejs graficzny (ang. GUI, Graphical User Interface). Czasami dochodzi do sytuacji, w której funkcjonalności rozszerzyć się nie da. Czasem też jakakolwiek próba pójścia w tym kierunku mogłaby nawet zostać stanowczo odrzucona przez zagorzałych użytkowników-tradycjonalistów. Coż w takich sytuacjach może zrobić biedny twórca?... Może rok w rok, te same - co do wartości merytorycznej - aplikacje obdarzać coraz to nowymi numerkami, choć z zasady różnić się będą tylko wyglądem. A my to kupujemy, choć (co prawda) nie wszyscy.

Należę do grupy osób skoncentrowanych wyłącznie na funkcjonalności. W swojej pracy zawsze staram się korzystać z jak najbardziej ogólnych wzorców projektowych.

Vista to nie Vista, 7-ka to nie 7-ka

I stało się... Dziś, po raz pierwszy od dłuższego czasu straciłem "programistyczną cierpliwość". Nie będę jednak wylewał tu swoich żalów - nie. Przecież nikomu nie jest to do szczęścia potrzebne. Ale każdą ludzką złość i frustrację można, przy odrobinie kombinatoryki, przedstawić w sposób nieco przyjemniejszy, z pożytkiem dla świata zawsze-młodych-duchem programistów.

Rzecz dotyczy wersji systemu Windows, jego komponentów, i takich tam...

Na potrzeby wykonywanego zawodu wybrałem system operacyjny Windows 7 Enterprise. Swego czasu z wielkim trudem przyszło mi powiedzieć "nie" tej części społeczności, która do dnia dzisiejszego wykorzystuje zasłużonego XP. Bynajmniej nie powiedziałem tego dosłownie. Po prostu projekty, nad którymi pracuję (ich przeważająca większość) z góry nie przewidują współpracy ze starszymi wersjami Windowsa. Z różnych względów... Przed 7-ką pojawiła się jednak Vista, znienawidzona przez niektórych, uwielbiana przez pozostałych.

O wydajności w aplikacjach .NET cz. 3

W poprzednim odcinku cyklu O wydajności w aplikacjach .NET omawialiśmy mechanizm Opakowywania i Rozpakowywania (ang. boxing/unboxing), czyli przekształcania pewnych typów danych w typ bazowy (tu Object) i z powrotem. Dziś zajmiemy się kwestią bardziej przyziemną, doskonale znaną wszystkim programistom... Ale czy na pewno?

Operacje na ciągach znaków

Środowisko .NET Framework udostępnia nam typ danych System.String na potrzeby reprezentowania ciągów znaków. Klasa String zawiera chyba wszystko "co tygrysy lubią najbardziej" i jest naprawdę obszernie i dokładnie opisana na stronach MSDN. Taki stan rzeczy wynika z prostego faktu - nasze całe życie opiera się na słowie pisanym i reprezentowaniu znaków w dowolnym języku naturalnym. W wirtualnym świecie słowa i znaki także odgrywają wiodącą rolę.

O wydajności w aplikacjach .NET cz. 2

Na wydajność nowotworzonego oprogramowania ma wpływ wiele czynników. Nie będę tu podejmował kwestii stosowanych algorytmów, ponieważ temat ten jest już dogłębnie opisany w wielu pozycjach książkowych. Poza tym każdy problem wymaga indywidualnego podejścia. W czym zatem, jak nie w algorytmice, szukać upragnionej wydajności? W rozwiązaniach uwzględniających specyficzną konstrukcję platformy .NET i jej wiodącego języka (C#).

Dziś, w ramach kontynuacji rozważań będących przedmiotem poprzedniego wpisu Wydajność w aplikacjach .NET, zajmiemy się tematem Opakowywania i Rozpakowywania (ang. boxing/unboxing) i związanymi z nim następstwami.

Nie każdy świeżo upieczony programista .NET zdaje sobie sprawę z tego jak zgubny wpływ na wydajność projektowanego oprogramowania może mieć nadmierne wykorzystanie przekształceń pewnych typów na inne, tym bardziej jeżeli całość odbywa się często w sposób niejawny ("po cichu"). Zagadnienie Opakowywania i Rozpakowywania nie jest jakoś nad wyraz skomplikowane i w zasadzie bardzo pokrótce opisane przez producenta. Z małym zastrzeżeniem:

O wydajności w aplikacjach .NET

Coraz częściej użytkownicy vortalu dobreprogramy opisują ulubione narzędzia programistyczne i wykorzystywane do różnorakich celów języki programowania. Takie wpisy budzą całkiem spore zainteresowanie wśród czytelników dobrychprogramów. Niemniej czytając komentarze pod wybranymi wpisami odnosi się wrażenie nieustannej bitwy ideologicznej, której stronami są zwolennicy tradycyjnych rozwiązań tj. programowania natywnego z wykorzystaniem języków pokroju C/C++ oraz zwolennicy kodu zarządzanego przez maszyny wirtualne (np. JVM dla Javy, CLR dla C# i pozostałych).

Nierzadko podejmowaną kwestią w tych burzliwych dyskusjach jest wydajność tworzonych aplikacji w zależności od wybranej technologii. Ech... ta wydajność... termin określający niepotrzebną bolączkę programistów naszych czasów.

W codziennej pracy wykorzystuję kilka narzędzi programistycznych z .NET'em na czele. Zaryzykuję stwierdzenie, że w dobie komputerów o tak znaczących mocach obliczeniowych i doskonale zoptymalizowanych procesów kompilacji i wykonywania kodu zarządzanego aplikacje działające w ramach platformy .NET nie ustępują

niedobreprogramy

W gąszczu burzliwych dyskusji dotyczących ostatnich nie-do-końca-legalnych działań (DDoS) sfrustrowanych internautów warto zwrócić uwagę na trochę z innej beczki, choć powszechny, problem współczesnego oprogramowania komputerowego.

Świeżo upieczony programista oczekuje bowiem, niemalże natychmiast, widocznych rezultatów swojej pracy (czyt. kolorowych, wielofunkcyjnych okienek wykonujących bardzo ważne rzeczy). I tak, jak grzyby po deszczu pojawiają się programy (małe i duże) zawierające błędy i niedopatrzenia. Może to kwestia dobranej do projektu metodologii programowania, może wynika to z chęci jak najszybszego wdrożenia na rynek produktu, a może zupełnie coś innego? Jaka by nie była przyczyna takiego stanu rzeczy, problem "błędów w oprogramowaniu" dotyczy każdego programisty.

Swego czasu podjąłem próbę wytłumaczenia osobie z poza środowiska tęgich głów "dlaczego niektóre programy się tak wieszają?". Choć zdaję sobie sprawę z tego, że w paru miejscach musiałem minąć się z rzeczywistością aby uzyskać pożądany efekt (czyt.