<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C Sharp &#8211; Strona Szoguna</title>
	<atom:link href="https://szogun1987.pl/show/tag/c-sharp/feed/" rel="self" type="application/rss+xml" />
	<link>https://szogun1987.pl</link>
	<description>Jeszcze wstawię tutaj jakiś głęboki cytat</description>
	<lastBuildDate>Sat, 22 Jun 2019 03:45:55 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.3.2</generator>
	<item>
		<title>Auth0 &#8211; Aplikacja do odpalania rakiet &#8211; backend</title>
		<link>https://szogun1987.pl/show/auth0-aplikacja-do-odpalania-rakiet-backend/430/</link>
					<comments>https://szogun1987.pl/show/auth0-aplikacja-do-odpalania-rakiet-backend/430/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 22 Jun 2019 03:42:46 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[auth0]]></category>
		<category><![CDATA[C Sharp]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=430</guid>

					<description><![CDATA[Zabezpieczenie backendu przed nieautoryzowanym dostępem jest najważniejszym elementem kontroli dostępu. Weryfikacja ograniczona do strony klienta działa jak folia aluminiowa na obrazku: W tym artykule pokażę jak utworzyłem prostą aplikację backendową, która wymaga autoryzacji z wykorzystaniem Auth0. Aplikacja jest stworzona w technologii .Net core, zanim zacząłem nad nią pracę miałem już zainstalowany pakiet .Net Core SDK, &#8230; <p class="link-more"><a href="https://szogun1987.pl/show/auth0-aplikacja-do-odpalania-rakiet-backend/430/" class="more-link">Czytaj dalej<span class="screen-reader-text"> Auth0 &#8211; Aplikacja do odpalania rakiet &#8211; backend</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p>Zabezpieczenie backendu przed nieautoryzowanym dostępem jest najważniejszym elementem kontroli dostępu. Weryfikacja ograniczona do strony klienta działa jak folia aluminiowa na obrazku:  </p>



<figure class="wp-block-image"><img decoding="async" src="https://external-preview.redd.it/sEGqsvUeXFmGdKccMwoQBZbch_t_aw1ImQCaj0J8jjM.jpg?auto=webp&amp;s=ce1ddd781e0b2fa92d6f13211bf9826b780f453b" alt=""/></figure>



<p><em> </em></p>



<span id="more-430"></span>



<p>W tym artykule pokażę jak utworzyłem prostą aplikację backendową, która wymaga autoryzacji z wykorzystaniem Auth0. </p>



<p>Aplikacja jest stworzona w technologii .Net core, zanim zacząłem nad nią pracę miałem już zainstalowany pakiet .Net Core SDK, aby je zainstalować należy wejść na stronę : <a href="https://dotnet.microsoft.com/download">https://dotnet.microsoft.com/download</a> i wybrać swój system operacyjny i podążać za instrukcjami.</p>



<p>Praca nad aplikacją jest znacznie prostsza z użyciem Visual Studio, ewentualnie Visual Studio Code albo JetBrains Rider, ich instalacja nie jest jednak konieczna.</p>



<p>Tworzenie aplikacji rozpocząłem od wpisania w linię poleceń:</p>



<pre class="prettyprint">dotnet new web --name SzogunUI.RocketService</pre>



<p>Polecenie to tworzy szkielet nowej aplikacji web o nazwie SzogunUI.RocketService</p>



<p>Następnie otworzyłem plik SzogunUI.RocketService\StartUp.cs i zmodyfikowałem metody Configure oraz ConfigureServices</p>



<pre class="prettyprint lang-cs">public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseMvc();
}</pre>



<p>Linijki services.AddMvc() oraz app.UseMvc() sprawiają, że aplikacja wspiera wzorzec Mvc, czyli jest podzielona na 3 elementy: Model &#8211; zawierający struktury danych wykorzystywane do komunikacji między aplikacją a światem zewnętrznym, Widok (View) &#8211; w tej aplikacji nie wykorzystywany, oraz logikę aplikacji w kontrolerach (Controller). </p>



<p>Warunek sprawdzający env.IsDevelopment() sprawia, że w trakcie prac nad projektem aplikacja będzie zwracała dużą ilość szczegółów technicznych dotyczących przyczyny błędu.</p>



<p>Do katalogu  SzogunUI.RocketService dodałem katalog Models, który zawiera Modele danych. Pierwszym z nich jest plik MissileType.cs zawierający następujący kod:</p>



<pre class="prettyprint lang-cs">namespace SzogunUI.RocketService.Models
{
    public enum MissileType
    {
        Bb,
        Parabelum,
        Cruise,
        TsarBomba
    }
}</pre>



<p>Jest to definicja typu wyliczeniowego (enum) zawierającego wszystkie typy pocisków jakie mogą być wysłane przez serwis. </p>



<p>Dodałem też klasę MissileSpec.cs zawierający klasę MissileSpec, opisującą ilość i typ pocisków wysyłanych przez użytkownika.</p>



<pre class="prettyprint lang-cs">namespace SzogunUI.RocketService.Models
{
    public class MissileSpec
    {
        public MissileType Type { get; set; }
        public int Amount { get; set; }
    }
}</pre>



<p>Następnie w katalogu SzogunUI.RocketLauncher utworzyłem katalog Controllers, a w tym katalogu umieściłem plik IndexController.cs zawierający następujący kod:</p>



<pre class="prettyprint">using Microsoft.AspNetCore.Mvc;
using SzogunUI.RocketService.Models;
namespace SzogunUI.RocketService.Controllers
{
    public class IndexController : Controller
    {
        [HttpGet]
        [Route("missile-types")]
        public IActionResult GetMissileTypes()
        {
            return Ok(new[]
            {
                MissileType.Bb,
                MissileType.Parabelum,
                MissileType.Cruise,
                MissileType.TsarBomba
            });
        }
        
        [HttpPut]
        [Route("locations/{latitude}/{longitude}")]
        public IActionResult PutMissilesToLocation(
            [FromRoute]double latitude, 
            [FromRoute]double longitude, 
            MissileSpec spec)
        {
            return Ok();
        }
    }
}</pre>



<p>Zawiera on klasę IndexController będącą pierwszym kontrolerem w naszej aplikacji. Klasa dziedziczy po klasie Controller, nie jest to wymagane, ale ułatwia pracę. Zawiera ona dwie metody:</p>



<ul><li>GetMissileTypes &#8211; zwracającą tablicę dostępnych typów pocisków</li><li>PutMissilesToLocation &#8211; pobierającą współrzędne geograficzne i specyfikację pocisków &#8211; odpowiedzialną za wysłanie pocisków w określoną lokalizację. Metodę pozostawiam pustą</li></ul>



<p>Kod zawiera także inne elementy: Atrybuty Route definiują ścieżkę pod jaką dana metoda będzie dostępna np. Route(&#8222;missile-type&#8221;) mówi, że akcja będzie dostępna pod adresem [adres-serwera]/missile-types np. https://localhost:5001/missile-types. Atrybut HttpGet oznacza, że metoda służy do pobierania danych i że można ją wywołać po prostu wpisując w przeglądarkę odpowiedni adres, istnieją atrybuty HttpPut, HttpPost i HttpDelete, które oznaczają że metoda wymaga zapytania put, post albo delete, ręczne wywołanie metod oznaczonych tymi atrybutami wymaga narzędzi typu Postman, curl czy wtyczka do chrome Advanced REST Client. Serwis będzie wywoływany przez aplikacje klienckie, a nie bezpośrednio przez użytkowników, nie musisz się więc przejmować tym utrudnieniem.</p>



<p>Działanie atrybutu FromRoute na parametrze metody najłatwiej wyjaśnić na przypadku metody PutMissilesToLocation. Ścieżka (atrybut Route) zawiera fragmenty {latitude} i {longitude} odpowiednie parametry metody posiadają Atrybut FromRoute oznacza to , że Mvc spróbuje dopasować fragment ścieżki i przekazać go jako parametr metody np. użycie ścieżki /locations/52.20/21.00 spowoduje wysłanie pocisków w kierunku Mokotowa.</p>



<p>Ostatnim elementem użytym w tym fragmencie kodu jest metoda Ok, do której można przekazać parametr. Generuje ona odpowiedź mówiącą, że obsługa wywołania się udała, a jej opcjonalny parametr jest zamieniany w zwracany tekst. Istnieją inne metody takie jak BadRequest albo UnAuthorized, mówiące, że nie udało się przetworzyć wywołania i dające aplikacji klienckiej pewne wskazówki o przyczynie tego problemu.</p>



<p>Na tym etapie po uruchomieniu aplikacji da się z nią rozmawiać po http, np .wpisując w przeglądarkę <a href="https://localhost:5001/missile-types">https://localhost:5001/missile-types</a>. Niestety zamiast nazw typów pocisków aplikacja zwraca:&nbsp;[0,1,2,3]. Aby to naprawić Należy do metody ConfiureServices w klasie Startup dodać wywołanie metody AddJsonOptions:</p>



<pre class="prettyprint">services
    .AddMvc()
    .AddJsonOptions(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()));</pre>



<p>Zaś w sekcji using dodać wpis</p>



<pre class="prettyprint">using Newtonsoft.Json.Converters;</pre>



<p>Teraz metoda zwraca już poprawny wynik.</p>


]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/auth0-aplikacja-do-odpalania-rakiet-backend/430/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Nasza droga do Reactive Extensions – cz. 3. – Meta</title>
		<link>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-3-meta/297/</link>
					<comments>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-3-meta/297/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Wed, 07 Nov 2018 10:59:02 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Reactive Extensions]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=297</guid>

					<description><![CDATA[W drugiej części serii&#160;opisałem jak zastosowanie wzorca Event Bus rozwiązało część naszych problemów, ale wprowadziła inne. W trzeciej i ostatniej części serii opiszę jak biblioteka Reactive Extensions&#160; (RX) rozwiązała te problemy, oraz dlaczego postanowiliśmy pozostawić niektóre obszary kodu bez zmian. Obserwator i obserwowany Wzorzec projektowy obserwatora i obserwowanego nie jest zbyt często wykorzystywany w aplikacjach &#8230; <p class="link-more"><a href="https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-3-meta/297/" class="more-link">Czytaj dalej<span class="screen-reader-text"> Nasza droga do Reactive Extensions – cz. 3. – Meta</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p>W <a href="https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-2-event-aggregator-na-ratunek/240/">drugiej części serii</a>&nbsp;opisałem jak zastosowanie wzorca Event Bus rozwiązało część naszych problemów, ale wprowadziła inne. W trzeciej i ostatniej części serii opiszę jak biblioteka Reactive Extensions&nbsp; (RX) rozwiązała te problemy, oraz dlaczego postanowiliśmy pozostawić niektóre obszary kodu bez zmian.</p>



<span id="more-297"></span>



<h2 class="wp-block-heading">Obserwator i obserwowany</h2>



<p>Wzorzec projektowy obserwatora i obserwowanego nie jest zbyt często wykorzystywany w aplikacjach .Net. Wiąże to się z faktem iż C# wspiera zdarzenia (events),&nbsp; które w większości przypadków są rozwiązaniem wystarczająco dobrym. Microsoft zauważył jednak, że istnieją bardziej rozbudowane scenariusze, takie jak nasze, w których nie zdają one egzaminu, dlatego dodał interfejsy IObserver&lt;T&gt; i IObservable&lt;T&gt;. Różnią się one od klasycznej definicji książkowej tego wzorca kilkoma szczegółami:</p>



<ul><li>Są generyczne (parametryzowane typem)&nbsp;</li><li>IObservable zawiera tylko metodę Subscribe akceptującą jako parametr obserwatora i zwracającą obiekt implementujący IDisposable, zamiast wywołania metody Unsubscribe należy wywołać metodę Dispose z wyniku metody Register</li><li>Obserwator posiada 3 metody&nbsp;OnNext, OnError i OnCompleted i jest bardziej skoncentrowany na obserwacji zmiany jednej wartości niż ogólnego stanu obserwowanego obiektu.</li></ul>



<h2 class="wp-block-heading">RX &#8211; Linq dla obserwatorów</h2>



<p>LINQ jest bardzo potężnym fragmentem standardowej biblioteki .Net opartym o 2 proste interfejsy IEnumerable i IEnumerator. Sprawił że operacje na kolekcjach stały się tak proste, że większość programistów .Net prędzej zmieni pracę niż zrezygnuje z ich używania. LINQ jest zbiorem metod rozszerzających i wzorcu dekoratora: większość metod jako parametr przyjmuje instancję IEnumerable i ewentualnie inne parametry mające wpływ na zachowanie metody. Wewnątrz tej metody jest tworzona i zwracana instancja klasy implementującej IEnumerable, która akceptuje&nbsp; parametry metody rozszerzającej jako parametry konstruktora. Metoda GetEnumerator tej klasy wywołuje metodę GetEnumerator oryginalnej kolekcji i przekazuje ją do konstruktora własnej klasy implementującej interfejs IEnumerator, wraz z parametrami swojego konstruktora. Dopiero ta klasa podczas wywoływania metody MoveNext analizuje parametry przekazane w konstruktorze i dokonuje decyzji czy wywoływać metodę MoveNext z oryginalnego Enumeratora, oraz jak przekształcić jej wynik, aby otrzymać docelową kolekcję.</p>



<p>Zarówno interfejs IEnumerable jak i IObservable opisują serię danych, pozwalają odczytywać kolejne elementy, oraz dostarczają informacji o tym czy seria zawiera więcej elementów. Podstawową różnicą jest fakt iż w przypadku IEnumerable to kod kliencki musi odczytywać kolejne elementy, a w przypadku IObservable to biblioteka wysyła kolejne elementy.</p>



<p>Na tym etapie utworzenie zestawu rozszerzeń do interfejsu IObservable wydaje się być dobrym pomysłem, tak właśnie powstała biblioteka Reactive Extensions. Pomysł okazał się tak dobry, że został zaadaptowany w większości języków programowania. Oprócz oryginalnej dokumentacji stworzonej przez Microsoft, powstała&nbsp;<a href="http://reactivex.io/">alternatywna wielo-platformowa dokumentacja</a> pozwalająca lepiej zrozumieć koncepcje. Po zapoznaniu się z nią postanowiliśmy wykorzystać bibliotekę do implementacji jednej z funkcjonalności. Zaskoczył nas fakt iż pomimo, że integracja z RX nie była uwzględniona w oryginalnej wycenie zadania, udało się je dostarczyć na czas.</p>



<h2 class="wp-block-heading">Dostarczanie wartości właściwości gdy zostaje podniesione zdarzenie</h2>



<p>Jak wspominałem w pierwszej części artykułu API, z którego korzystamy składa się w większości z par właściwość &#8211; zdarzenie. Kluczowe więc dla nas było żeby istniał sposób na&nbsp; dostarczenie wartości właściwości po podniesieniu zdarzenia. Na szczęście okazało się, że RX posiada odpowiednią metodę</p>



<pre class="prettyprint lang-cs">var sizeObservable =
    Observable
        .FromEventPattern(
            handler =&gt; someObject.SizeChanged += handler,
            handler =&gt; someObject.SizeChanged -= handler)
        .Select(o =&gt; someObject.Size);</pre>



<p>Ponieważ w większości przypadków nasz kod wymagał aby aktualna wartość właściwości natychmiastowo wyświetliła się na ekranie, stworzyliśmy własne rozszerzenie, które do powyższej metody dodawało dostarczenie tej wartości w momencie subskrypcji.</p>



<h2 class="wp-block-heading">Komunikacja między wątkami</h2>



<p>Ponieważ nasza aplikacja wykorzystuje wiele wątków, wsparcie przesyłania wiadomości pomiędzy wątkami była czymś czego oczekiwaliśmy. RX posiada metodę ObserveOn, która jako parametr przyjmuje obiekt typu Dispatcher. Niestety nie mogliśmy jej wykorzystać ponieważ inna biblioteka, którą wykorzystujemy, ukrywa ten obiekt pod własną abstrakcją. Na szczęście okazało się, że napisanie takiego rozszerzenia (Dispatch) własnoręcznie nie jest szczególnie trudne: 1 metoda rozszerzająca, 2 klasy mniej niż 100 linijek kodu.</p>



<h2 class="wp-block-heading">Obserwowanie wielu źródeł na raz</h2>



<p><br>Często to co użytkownik&nbsp;widzi na ekranie jest wyliczane na podstawie kilku wartości dostarczanych przez bibliotekę.  Kolejną fukcjonalnością jakiej oczekiwaliśmy od RX była możliwość łączenia wartości z różnych źródeł. Rozwiązaniem jest metoda CombineLatest przyjmująca jako parametr kilka obiektów IObservable i funkcję która jako parametry akceptuje ostatnie znane wartości dostarczone przez obiekty Observable, a jako wynik zwraca wartość dostarczoną do obserwatora.</p>



<pre class="prettyprint lang-cs">Observable
    .CombineLatest(
        firstObservable,
        secondObservable,
        thirdObservable,
        (firstValue, secondValue, thirdValue) =&gt; firstValue * secondValue * thirdValue);</pre>



<h2 class="wp-block-heading">Poprawa wydajności</h2>



<h3 class="wp-block-heading">Filtrowanie wartości</h3>



<p>Podobnie jak LINQ, RX posiada metodę Where, pozwalającą usunąć z sekwencji wartości nie spełniających określonych warunków, odciążając w ten sposób obserwatora. Dodam że inne implementacje RX nazywają tą metodę Filter.</p>



<h3 class="wp-block-heading">Usuwanie duplikatów</h3>



<p>RX posiada metodę Distinct, która gwarantuje, że obserwator otrzyma każdą wartość tylko raz.W naszej aplikacji jednak okazało się, że znacznie bardziej użyteczna jest metoda DistinctUntilChanged, która usuwa duplikaty następujące po sobie. Ustawienie CombineLatest, DistinctUntilChanged i Dispatch w odpowiedniej kolejności pozwoliło wyeliminować większość nadmiarowej komunikacji między wątkami.</p>



<h3 class="wp-block-heading">Debouncing</h3>



<p>RX zwiera metodę Debounce. Która ogranicza częstotliwość dostarczania kolejnych wiadomości. Jest ona użyteczna jeżeli nowe wartości mogą przychodzą tak często, że użytkownik nie jest w stanie ich konsumować, a utrata części komunikatów nie jest problemem. Dobrym przykładem może tu być czujnik poziomu płynu chłodniczego, w trakcie jazdy po wyboistej drodze, gdy znajdujemy się w okolicach krytycznie niskiego poziomu. W takim przypadku czujnik co chwila wysyła informację, że wszystko jest OK albo że należy dolać płynu, to sprawia, że kontrolka na desce cały czas by mrugała denerwując użytkownika. Po zastosowaniu metody Debounce kontrolka zapalałaby się na kilka &#8211; kilkanaście sekund i gasła.</p>



<h2 class="wp-block-heading">Testy jednostkowe</h2>



<p>W naszym projekcie cały czas staramy się podnosić poziom pokrycia kodu testami. Jeżeli to ułatwia pracę stosujemy biblioteki Moq i NSubstitute. Niestety obie te biblioteki domyślnie zwracają null dla właściwości typu IObservable, co zmusza nas do rozszerzenia kodu inicjującego test. Nie jest to jednak tak uciążliwe na jakie wygląda.</p>



<h2 class="wp-block-heading">Analiza problemów z produkcji</h2>



<p>Podobnie jak LINQ i metody asynchroniczne, generuje bardzo długie i nieczytelne stosy wywołań. Czasami zdarza się, że w całym stosie nie ma żadnej linijki kodu należącej do naszej aplikacji.</p>



<h2 class="wp-block-heading">Nie rezygnujemy z event-agregatora</h2>



<p>Event agregator ma miejsce w naszym projekcie i nie planujemy go usuwać. Istnieją zdarzenia o których informujemy przy pomocy obydwóch mechanizmów.</p>



<p>Nasza podróż przez różne rozwiązania, nauczyła nas, że jeżeli istnieją różne rozwiązania jednego problemu, to każde z nich ma swoje wady i zalety, i nie należy się kurczowo trzymać jednego rozwiązania.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-3-meta/297/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Nasza droga do Reactive Extensions &#8211; cz. 2 &#8211; Event Aggregator na ratunek</title>
		<link>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-2-event-aggregator-na-ratunek/240/</link>
					<comments>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-2-event-aggregator-na-ratunek/240/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sun, 16 Sep 2018 08:38:11 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Reactive Extensions]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=240</guid>

					<description><![CDATA[W poprzednim wpisie opisałem problem z wyborem architektury aplikacji przed jakim stanął nasz zespół. W drugiej części opiszę jakie problemy udało się rozwiązać dzięki wzorcowi event aggregator, jakie pozostały nie rozwiązane, a jakie powstały w wyniku jego użycia.]]></description>
										<content:encoded><![CDATA[
<p>W <a href="https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-1-wstep/232/">poprzednim wpisie</a> opisałem problem z wyborem architektury aplikacji przed jakim stanął nasz zespół. W drugiej części opiszę jakie problemy udało się&nbsp;rozwiązać dzięki wzorcowi event aggregator, jakie pozostały nie rozwiązane, a jakie powstały w wyniku jego użycia.</p>



<span id="more-240"></span>



<p>Wzorzec <a href="https://martinfowler.com/eaaDev/EventAggregator.html">Event aggregator</a>, zwany czasami mediatorem albo event busem, dostarcza kanału komunikacji pomiędzy modułami aplikacji, ograniczając powiązania między nimi: moduł wysyłający wiadomość nie ma pojęcia kto na niego zareaguje, nie wiem nawet czy ktokolwiek to zrobi. Moduł oczekujący na wiadomość zazwyczaj nie musi znać nadawcy, interesuje go tylko treść wysłanej wiadomości.</p>



<p>Modułem naszej aplikacji, w którym ten wzorzec jest szczególnie użyteczny, jest obszar powiadomień.</p>



<figure class="wp-block-image"><img decoding="async" fetchpriority="high" width="1240" height="480" src="https://szogun1987.azureedge.net/wp-content/windows-desktop.png" alt="" class="wp-image-274"/></figure>



<p>W aplikacji istnieje tylko jedna instancja klasy odpowiadającej za ten obszar, klasa ta nasłuchuje na zdarzenia wysyłane przez wiele różnych klas. Bez tego wzorca wyświetlenie powiadomienia o przyjściu nowej wiadomości wymagałoby śledzenia dostępności samego serwisu wiadomości, zmian na liście rozmów oraz zmian na liście wiadomości w każdej rozmowie. Co gorsza każdy moduł, który chciałby reagować na przyjście nowej wiadomości musiałby powtórzyć znaczną część tego kodu. Dzięki event-aggregatorowi ta część kodu jest napisana raz, w klasie która wysyła wiadomość, natomiast klasy zainteresowane przyjściem nowej wiadomości wywołują tylko jedną linijkę:</p>



<pre class="prettyprint lang-cs">_messageAggregator.Register<IncomingMessageNotification>(MessageHandlingMethod);</pre>



<p>Drugim problemem jakim rozwiązał ten wzorzec, jest komunikacja między wątkami. Napisaliśmy jedną metodę rozszerzającą do event-aggregatora, która przenosi obsługę powiadomienia na główny wątek aplikacji:</p>



<pre class="prettyprint lang-cs">public static void RegisterOnDispatcher(
    this MessageAggregator self,
    DispatcherService dispatcherService,
    Action handler)
{
    self.Register(message =&gt; dispatcherService.Invoke(() =&gt;f handler(message)));
}</pre>



<p>Zrozumienie ciała metody wymaga chwili zastanowienia, jednak jej użycie jest proste:</p>



<pre class="prettyprint lang-cs">_messageAggregator.RegisterOndispatcher<IncomingMessageNotification>(MessageHandlingMethod);</pre>



<h2 class="wp-block-heading">Problemy z event-aggregatorem</h2>



<p>Wzorzec ten jest tak wygodny, że bardzo szybko zdominował znaczną część naszego kodu. W pewnym momencie zorientowaliśmy się jednak że powoduje on pewne problemy, a innych nie rozwiązuje.</p>



<p>Po pierwsze wiele klas wylicza swój stan początkowy na podstawie stanu serwisu, a na wiadomość zapisuje się żeby odświeżyć swój stan, co powoduje że każda z tych klas ma dwie zależności: serwis i event-aggregator.</p>



<p>Wysłanie wiadomości przez event-aggregatora wymaga napisania dodatkowej klasy, ponieważ programiści są z natury leniwi starają się pominąć ten krok gdy tylko jest to możliwe, nawet kosztem &#8222;wycieku abstrakcji&#8221;. Zdarzały się przypadki gdy mieliśmy serwis, który nasłuchiwał na zdarzenia z dwóch innych serwisów i wyliczał jakąś wartość, jednak nie wysyłał żadnego powiadomienia o zmianie tej wartości. Klasy które korzystały z tej klasy nasłuchiwały na zdarzenia z oryginalnych serwisów.</p>



<p>Nasza aplikacja pozwala na zmianę wielu ustawień &#8222;w locie&#8221;, czyli bez konieczności restartu aplikacji. W momencie zapisu ustawień &#8222;menadżer ustawień&#8221; wysyła wiadomość. Wiele klas jest na nią zarejestrowanych i wykonuje swoją logikę, nawet jeśli konkretne ustawienie nie uległo zmianie, aby ograniczyć ten efekt dodaliśmy do wiadomości dodatkową informację o tym, które wartości uległy zmianie, co jednak zmusza nas do dopisywania kilku dodatkowych linijek kodu za każdym razem gdy pojawia się nowe ustawienie.</p>



<p>W aplikacji pojawiły się problemy wydajnościowe związane z komunikacją między wątkami. Co prawda wywołanie metody Dispatcher.Invoke nie jest szczególnie ciężkie i nie należy się go bać, a już na pewno nie kosztem niepoprawnego działania programu, jednak wywoływanie jej kilkanaście tysięcy razy może przyprawić o zadyszkę nawet mocne komputery i spowodować &#8222;zawieszenie&#8221; się aplikacji. Wspomniana wcześniej metoda RegisterOnDispatcher powodowała, że &#8222;Handler&#8221; był uruchamiany na głównym wątku aplikacji, nawet w przypadkach gdy efektywnie nic nie robił np. pierwsza linijka obsługi zmiany ustawień zawierała sprawdzenie czy ustawienie, którego zmianą jest klasa jest zainteresowana, nie uległo zmianie. Trudniejszym do wyśledzenia przypadkiem był przypadek gdy ustawienie uległo zmianie, ale efektywna wartość wyliczona na jego podstawie pozostała bez zmian. W tej architekturze były to problemy bardzo trudne do naprawy.</p>



<p>W<a href="https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-3-meta/297/"> kolejnej części artykułu</a> opiszę jak biblioteka Reactive Extensions rozwiązała nasze problemy.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-2-event-aggregator-na-ratunek/240/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Cloud Foundry &#8211; notatki &#8211; Pierwsza aplikacja w chmurze</title>
		<link>https://szogun1987.pl/show/cloud-foundry-notatki-pierwsza-aplikacja-w-chmurze/244/</link>
					<comments>https://szogun1987.pl/show/cloud-foundry-notatki-pierwsza-aplikacja-w-chmurze/244/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Mon, 10 Sep 2018 09:32:41 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Cloud foundry]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=244</guid>

					<description><![CDATA[Aby uruchomić aplikację w chmurze potrzebujemy dwóch rzeczy: aplikacji i chmury.
Aby wygenerować aplikację użyjemy linii poleceń i komendy dotnet. ]]></description>
										<content:encoded><![CDATA[
<p>Aby uruchomić aplikację w chmurze potrzebujemy dwóch rzeczy: aplikacji i chmury.</p>



<p>Aby wygenerować aplikację użyjemy linii poleceń i komendy dotnet. </p>



<pre class="prettyprint">dotnet new mvc --name Sample.Api.App</pre>



<p class="has-background has-very-light-gray-background-color">Jeżeli powyższa komenda nie działa prawdopodobnie powinieneś zainstalować <a href="https://www.microsoft.com/net/learn/get-started-with-dotnet-tutorial">.Net SDK</a></p>



<span id="more-244"></span>



<p>Aby upewnić się czy aplikacja działa wpiszmy  w linię komend</p>



<pre class="prettyprint">cd Sample.Api.App
dotnet restore
dotnet run</pre>



<p>Poczekaj aż na ekranie pojawi się komunikat</p>



<pre class="prettyprint">Now listening on: https://localhost:5001
Now listening on: http://localhost:5000</pre>



<p>I otwórz stronę <a href="https://localhost:5001/api/values">https://localhost:5001/api/values</a> strona powinna zawierać następujący tekst:</p>



<pre class="prettyprint">["value1","value2"]</pre>



<p>Wróć do konsoli i wciśnij Ctrl+C</p>



<h2 class="wp-block-heading">Udostępnijmy aplikację w chmurze</h2>



<p class="has-background has-very-light-gray-background-color">W <a href="https://szogun1987.pl/show/cloud-foundry-notatki-wstep/220/">poprzednim artykule</a> proponowałem Ci zainstalowanie aplikacji cf-cli i założenie konta na stronie <a href="https://run.pivotal.io">run.pivotal.io</a> wszystkie dalsze fragmenty kodu będą zakładały, że tak właśnie zrobiłeś.</p>



<p>Aby udostępnić aplikację użyję narzędzia cf-cli. Narzędzie może współpracować z wieloma wdrożeniami CF dlatego należy wskazać środowisko na którym aplikacja ma zostać wdrożona:</p>



<pre class="prettyprint">cf api api.run.pivotal.io</pre>



<p>Aplikacja musi też znać login i hasło, aby je podać należy użyć polecenia:</p>



<pre class="prettyprint">cf login</pre>



<p>po podać login i hasło użyte podczas rejestracji. Ostatnim krokiem jest &#8222;wypchnięcie&#8221; aplikacji do chmury, aby to zrobić wpisz w linię poleceń:</p>



<pre class="prettyprint">cf push sample-api --random-route</pre>



<p>Parametr sample-api to nazwa aplikacji, która jest obowiązkowa. Parametr &#8211;random-route jest opcjonalny i oznacza, że chmura wylosuje dla nas ścieżkę, pod którą aplikacja będzie dostępna. Pominięcie tego parametru sprawi, że narzędzie spróbuje opublikować aplikację pod adresem: <a href="https://sample-api.cfapps.io">sample-api.cfapps.io</a>, który prawdopodobnie będzie zajęty ze względu na fakt, iż jest to środowisko współdzielone przez wielu użytkowników. Ścieżkę można też ustawić ręcznie podając parametr &#8211;route</p>



<pre class="prettyprint">cf push sample-api --route moja-unikalna-personalna-sciezka</pre>



<p>Co spowoduje próbę publikacji pod adresem <a href="https://moja-unikalna-personalna-sciezka.cfapps.io">moja-unikalna-personalna-sciezka.cfapps.io</a></p>



<p>Narzędzie powinno wyświetlić masę tekstu kończącego się czymś podobnym do:</p>



<pre class="prettyprint">Waiting for app to start...

name:              sample-api
requested state:   started
routes:            sample-api-optimistic-porcupine.cfapps.io
last uploaded:     Thu 06 Sep 20:47:01 CEST 2018
stack:             cflinuxfs2
buildpacks:        dotnet-core

type:            web
instances:       1/1
memory usage:    1024M
start command:   cd ${DEPS_DIR}/0/dotnet_publish &amp;&amp; ./Sample.Api.App
                 --server.urls http://0.0.0.0:${PORT}
     state     since                  cpu    memory    disk
#0   running   2018-09-06T18:47:17Z   0.0%   0 of 1G   0 of 1G</pre>



<p>Linijka zaczynająca się od &#8222;routes:&#8221; wskazuje adres aplikacji. W moim przypadku jest to: &#8222;sample-api-optimistic-porcupine.cfapps.io&#8221;, jeżeli wszystko poszło dobrze po otworzeniu w przeglądarce adresu https://[ścieżka aplikacji]/api/values (w moim przypadku <a href="https://sample-api-optimistic-porcupine.cfapps.io/api/values">https://sample-api-optimistic-porcupine.cfapps.io/api/values</a>) powinniśmy ponownie zobaczyć stronę zawierającą:</p>



<pre class="prettyprint">["value1","value2"]</pre>



<p>W kolejnym artykule opowiem co w tym procesie można zrobić lepiej.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/cloud-foundry-notatki-pierwsza-aplikacja-w-chmurze/244/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Nasza droga do Reactive Extensions &#8211; cz. 1 &#8211; Wstęp</title>
		<link>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-1-wstep/232/</link>
					<comments>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-1-wstep/232/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Thu, 06 Sep 2018 17:27:02 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Reactive Extensions]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=232</guid>

					<description><![CDATA[Jeden z produktów jakie ostatnio rozwijaliśmy w naszym zespole, jest aplikacją desktopową opartą o rozbudowaną bibliotekę, która dostarczała spójne API do komunikacji, opartej o różne protokoły związane z telekomunikacją, co sprawiało że generowała naprawdę dużo sygnałów. Chcesz wiedzieć jak sobie z tym poradziliśmy? ]]></description>
										<content:encoded><![CDATA[
<p class="has-background has-pale-cyan-blue-background-color">Artykuł w wersji anglojęzycznej jest dostępny na blogu firmy <a href="http://blog.grapeup.com/read/our-way-to-reactive-extensions-24">Grape Up</a></p>



<p>Jeden z produktów jakie ostatnio rozwijaliśmy w naszym zespole, jest aplikacją desktopową opartą o rozbudowaną bibliotekę, która dostarczała spójne API do komunikacji, opartej o różne protokoły związane z telekomunikacją, co sprawiało że generowała naprawdę dużo sygnałów.</p>



<span id="more-232"></span>



<h2 class="wp-block-heading">Architektura biblioteki</h2>



<p>Większość klas w tej bibliotece pasowała do takiego wzorca:</p>



<pre class="prettyprint lang-cs">public class Class1
{
    public void SetDescription(string description, CompletionHandler handler)
    {
         /* Some logic here */
    }

    public void SetSize(int size, CompletionHandler handler)
    {
        /* Some logic here */
    }

    public string Description { get; private set; }

    public int Size { get; private set; }

    public event EventHandler DescriptionChanged;

    public event EventHandler SizeChanged;
}
</pre>



<ul><li>Metody SetDescription i SetSize wysyłają wartość przekazaną jako pierwszy parametr i wywołują metodę przekazaną jako Handler gdy serwer potwierdzi albo odrzuci żądanie</li><li>Właściwości Description i Size zwracają ostatnią znaną wartość</li><li>Zdarzenia DescriptionChanged i SizeChanged są uruchamiane gdy serwer powiadomi aplikację o zmianie wartości &#8211; niezależnie czy zmiana była spowodowana przez wywołanie metody Set* czy przez inne interakcje z serwerem np. działanie drugiej aplikacji</li></ul>



<p>Biblioteka przetwarza wszystkie żądania na swojej własnej wewnętrznej puli wątków co ma swoje zalety i wady. Podstawową zaletą był fakt iż biblioteka, sama z siebie, nie wpływała na działanie wątku głównego aplikacji. Wadą był fakt iż wszystkie callbacki i zdarzenia podnoszone przez bibliotekę były uruchamiane na innym wątku, co wymuszało opracowanie jakiegoś mechanizmu do komunikacji między wątkami.</p>



<h2 class="wp-block-heading">Ręczne zarządzanie wątkami &#8211; Nie chcesz tego robić</h2>



<p>Już od początku rozwoju aplikacji zorientowaliśmy się, że ręczna komunikacja między wątkami kończy się powstaniem dużej ilości długiego i powtarzalnego kodu, który wygląda mniej więcej tak:</p>



<pre class="prettyprint lang-cs">public class SomeOtherClass : IDisposable
{
    private readonly SomeClass _someObject;
    private readonly DispatcherService _dispatcherService;

    public SomeOtherClass(
        SomeClass someObject,
        DispatcherService dispatcherService)
    {
        _someObject = someObject;
        _dispatcherService = dispatcherService;

        _someObject.DescriptionChanged += SomeObjectOnDescriptionChanged;
        _someObject.SizeChanged += SomeObjectOnSizeChanged;
    }
    
    private void SomeObjectOnDescriptionChanged(object sender, EventArgs e)
    {
        _dispatcherService.Invoke(LoadState);
    }

    private void SomeObjectOnSizeChanged(object sender, EventArgs e)
    {
        _dispatcherService.Invoke(LoadState);
    }

    private void LoadState()
    {
        PropertyVisibleOnUI = $"Description: {_someObject.Description} Size: {_someObject.Size}";
    }
    
    public string PropertyVisibleOnUI { get; set; }

    public void Dispose()
    {
        _someObject.DescriptionChanged -= SomeObjectOnDescriptionChanged;
        _someObject.SizeChanged -= SomeObjectOnSizeChanged;
    }
}</pre>



<p>Kod staje się jeszcze bardziej złożony jeżeli założymy, że niektóre właściwości klasy są złożonymi obiektami, które mają właściwości, zdarzenia, metody asynchroniczne. A takich warstw może być znacznie więcej.</p>



<p>API do obsługi wiadomości tekstowych napisane w tej konwencji mogło wyglądać tak:</p>



<pre class="prettyprint lang-cs">public interface IConversationService
{
    event EventHandler ConverstionStarted;
    event EventHandler ConversationEnded; 
    IEnumerable Conversations { get; }
}

public interface IConversation
{
    event EventHandler MessageAdded;
    void SendMessage(string body, CompletionHandler handler); 
    IEnumerable Messages { get; }
}

public interface IMessage
{
    event EventHandler IsReadChanged;
    bool IsMine { get; }
    string Body { get; }
    bool IsRead { get; }
}</pre>



<p>Koniecznie potrzebowaliśmy lepszego rozwiązania. W drugiej <a href="https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-2-event-aggregator-na-ratunek/240/">części artykułu</a> opiszę jak wzorzec event-aggregator pomógł nam pokonać te problemy.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/nasza-droga-do-reactive-extensions-cz-1-wstep/232/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Spotkanie z TaskCompletionSource &#8211; Cz. 3 Niespełnione obietnice</title>
		<link>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-3-niespelnione-obietnice/37/</link>
					<comments>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-3-niespelnione-obietnice/37/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Wed, 08 Mar 2017 11:08:23 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=37</guid>

					<description><![CDATA[Trzecią i ostatnią część artykułu poświęcam rzadkiemu ale bardzo trudnemu w analizie problemowi, który może pojawić się w czasie adaptacji API w wykorzystaniem TaskCompletionSource.]]></description>
										<content:encoded><![CDATA[<p>Trzecią i ostatnią część artykułu poświęcam rzadkiemu ale bardzo trudnemu w analizie problemowi, który może pojawić się w czasie adaptacji API w wykorzystaniem TaskCompletionSource.</p>
<p><span id="more-37"></span></p>
<p>Zacznę od takiego niewinnego kawałku kodu:</p>
<div class="code">
<pre class="prettyprint lang-cs">class Adapter
{
    public Task&lt;int&gt; GetNextInt()
    {
        var api = new CallbacksApi();
        var taskCompletionSource = new TaskCompletionSource&lt;int&gt;();
    
        api.GetNextInt((result, exception) =&gt;
        {
            if (exception != null)
            {
                taskCompletionSource.SetException(exception);
            }
            else
            {
                taskCompletionSource.SetResult(result);
            }
        });
        
        return taskCompletionSource.Task;
    }
}</pre>
</div>
<p>Kod wydaje się poprawny. Co lepsze będzie działać w czasie testów dymnych, prawdopodobnie przejdzie testy funkcjonalne. Kod ten może jednak powodować pojawianie się błędów typu: &#8222;Ta operacja czasami nie kończy się przez pół godziny&#8221;, &#8222;aplikacja chodzi wolno&#8221; albo &#8222;program się zawiesza&#8221;. Co gorsza nikt nie będzie w stanie dostarczyć powtarzalnego scenariusza.</p>
<p>Winnym okazuje się być Garbage Collector, który może w tym przypadku błędnie stwierdzić, że nikt nie potrzebuje obiektu CallbacksApi, bo nikt nie posiada do niego referencji.</p>
<p><img decoding="async" class="img-responsive" src="http://static.szogun1987.pl/img/events-and-tasks/ObjectReferences.svg" alt="Referencje pomiędzy obiektami" /></p>
<p>Pierwszym sposobem &#8222;obejścia&#8221; tego problemu może być &#8222;przytrzymanie&#8221; referencji do API w jakimś obiekcie, który żyje dłużej. W kodzie powyżej może być to klasa obiekt typu Adapter.</p>
<div class="code">
<pre class="prettyprint lang-cs">class Adapter
{
    private CallbacksApi _api = new CallbacksApi();
    public Task&lt;int&gt; GetNextInt()
    {
        var taskCompletionSource = new TaskCompletionSource&lt;int&gt;();
    
        _api.GetNextInt((result, exception) =&gt;
        {
            if (exception != null)
            {
                taskCompletionSource.SetException(exception);
            }
            else
            {
                taskCompletionSource.SetResult(result);
            }
        });
        
        return taskCompletionSource.Task;
    }
}</pre>
</div>
<p>Sprawa się komplikuje gdy nowe CallbacksApi musi być tworzone z każdym wywołaniem GetNextInt. Brzydkim ale szybkim obejściem tego problemu jest użycie kolekcji:</p>
<div class="code">
<pre class="prettyprint lang-cs">class Adapter
{
    private List&lt;CallbacksApi&gt; _apiReferences = new List&lt;CallbacksApi&gt;();
    private object _apiReferencesLockRoot = new object();
    public Task&lt;int&gt; GetNextInt()
    {
        var api = new CallbacksApi();
        var taskCompletionSource = new TaskCompletionSource&lt;int&gt;();
        lock(_apiReferencesLockRooti)
        {
            _apiReferences.Add(api);
        }
    
        api.GetNextInt((result, exception) =&gt;
        {
            lock(_apiReferencesLockRooti)
            {
                _apiReferences.Add(api);
            }
            if (exception != null)
            {
                taskCompletionSource.SetException(exception);
            }
            else
            {
                taskCompletionSource.SetResult(result);
            }
        });
        
        return taskCompletionSource.Task;
    }
}</pre>
</div>
<p>Ten kod działa ale wszyscy się chyba zgodzą że najładniejszy to on nie jest. W dodatku jeżeli referencja do obiektu typu Adapter nie jest nigdzie przetrzymywana przez dłuższy czas to powyższe rozwiązania i tak nie zadziałają. Na szczęście Microsoft pomyślał o tym problemie i TaskCompletionSource posiada dodatkowy parametr konstruktora &#8222;state&#8221;, którego można przekazać cokolwiek. Obiekt ten jest przypisany do właściwości AsyncState wynikowego Taska, przez co GC zostawi go w spokoju.</p>
<div class="code">
<pre class="prettyprint lang-cs">class Adapter
{
    public Task&lt;int&gt; GetNextInt()
    {
        var api = new CallbacksApi();
        var taskCompletionSource = new TaskCompletionSource&lt;int&gt;(api);
    
        api.GetNextInt((result, exception) =&gt;
        {
            if (exception != null)
            {
                taskCompletionSource.SetException(exception);
            }
            else
            {
                taskCompletionSource.SetResult(result);
            }
        });
        
        return taskCompletionSource.Task;
    }
}</pre>
</div>
<p>Kod klas, które stworzyłem na potrzeby tego wpisu znajduje się w tym punkie <a href="https://github.com/szogun1987/events-and-tasks/tree/master/src/Szogun1987.EventsAndTasks/Callbacks/NeverCalledback">Githuba</a>, natomiast testy do nich <a href="https://github.com/szogun1987/events-and-tasks/blob/master/src/Szogun1987.EventsAndTasks.Tests/NeverCalledBackTests.cs">tutaj</a>. Testy zwracają oczekiwany wynik tylko po zbudowaniu projektu w trybie Release, a właściwie to nie do końca zwracają. Test dla klasy FixedAdapter przechodzi i tak ma być. Test dla klasy BrokenAdapter nie przechodzi i to także jest zgodne z moimi oczekiwaniami.</p>
<p>Mam natomiast problem z testem dla klasy WorkedAroundAdapter, teoretycznie linijka Assert.NotNull(adapter) powinna sprawić że test przejdzie, ten jednak przejść nie chce i nie mam pojęcia dlaczego. Postanowiłem więc postawić znaczną ilość piwa, zgrzewkę 24 Tyskiego albo jego równowartość w innym gatunku, pierwszej osobie która mi to wytłumaczy.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-3-niespelnione-obietnice/37/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Spotkanie z TaskCompletionSource &#8211; Cz. 2 Zdarzenia a zadania</title>
		<link>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-2-zdarzenia-a-zadania/36/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Tue, 07 Mar 2017 09:18:50 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=36</guid>

					<description><![CDATA[W drugiej części serii zajmę się adaptacją API, w którym asynchroniczność jest zrealizowana przez zdarzenia (ang. events).]]></description>
										<content:encoded><![CDATA[<p>Jedną z prób ogarnięcia asynchroniczności było wykorzystanie mechanizmu zdarzeń (event). Onegdaj istniały takie technologie jak WCF &#8211; służący do wystawiania na świat API po http oraz Silverlight, który miał robić to co dzisiaj <s>Flash</s> javascript. I jak się generowało klasy pozwalające korzystać z API WCF w SL to wynikowe klasy przypominały taki kod:</p>
<div class="code">
<pre class="prettyprint lang-cs">public class Proxy
{
    void Method1(int argument);
    event EventHandler&lt;EventArgs&lt;Result1&gt;&gt; Method1Completed;
    event EventHandler&lt;FailureEventArgs&gt; Method1Failed;

    void Method2();
    event EventHandler&lt;EventArgs&lt;Result2&gt;&gt; Method1Completed;
    event EventHandler&lt;FailureEventArgs&gt; Method1Failed;
}</pre>
</div>
<p><span id="more-36"></span></p>
<p>Ale poczułem się staro. Podobny wzorzec był stosowany też w innych technologiach. Ma on wiele wad w porównaniu do kolbaków. Na początek nie istnieje żadna gwarancja że jeżeli wywołam Method1 z argumentem 1 po czym wywołam Method1 z argumentem 2 to event Method1Completed dla 1 przyjdzie przed tym samym eventem dla 2. Na potrzeby dalszych rozważań uznam, że opakowanie w Task i użycie słów async i await sprawi że wywołanie z 2 nie nastąpi przez eventem dla 1, co nie musi być prawdą ale zazwyczaj jest.</p>
<p>Podejście to sprawdza się nie źle w jednym przypadku: akcja się wywołuje jak się uda podejmowane jest jedno zawsze to samo działanie, jak nie to drugie.</p>
<div class="code">
<pre class="prettyprint lang-cs">// Constructor
public ClientClass()
{
    _eventApi = new EventApi();
    _eventApi.GetNextIntCompleted += EventApiOnGetNextIntCompleted;
    _eventApi.GetNextIntFailed += EventApiOnGetNextIntFailed;
}

private void EventApiOnGetNextIntCompleted(object sender, ResultEventArgs resultEventArgs)
{
    MessageBox.Show(resultEventArgs.Result);
}

private void EventApiOnGetNextIntFailed(object sender, FailureEventArgs failureEventArgs)
{
    MessageBox.Show("Something gone wrong");
}</pre>
</div>
<p>Sytuacja jednak komplikuje się znacząco gdy w momencie zakończenia zadania potrzebna jest informacja znana przy jego rozpoczęciu:</p>
<div class="code">
<pre class="prettyprint lang-cs">public void GetNextIntForClient(Client client)
{
    EventHandler&lt;ResultEventArgs&gt; successHandler = null;
    EventHandler&lt;FailureEventArgs&gt; failureHandler = null;
    
    successHandler = (sender, args) =&gt;
    {
        _eventApi.GetNextIntCompleted -= successHandler;
        _eventApi.GetNextIntFailed -= failureHandler;
        MessageBox.Show(string.Format("{1} was chosen for client {0}", client.Name, args.Result));
    };

    failureHandler = (sender, args) =&gt;
    {
        _eventApi.GetNextIntCompleted -= successHandler;
        _eventApi.GetNextIntFailed -= failureHandler;
        MessageBox.Show(string.Format("Unable to choose value for client {0}", client.Name));
    };
    
    _eventApi.GetNextIntCompleted += successHandler;
    _eventApi.GetNextIntFailed += failureHandler;

    _eventApi.GetNextInt();
}</pre>
</div>
<p>Dla porównania kod oparty o async/await</p>
<div class="code">
<pre class="prettyprint lang-cs">public async void GetNextIntForClient(Client client)
{
    try
    {
        await _taskApi.GetNextInt();
        MessageBox.Show(string.Format("{1} was chosen for client {0}", client.Name, args.Result));
    }
    catch (Exception exception)
    {
        MessageBox.Show(string.Format("Unable to choose value for client {0}", client.Name));
    }
}</pre>
</div>
<p>Opakowanie zdarzeń w zadania nie jest proste i opiera się na kodzie podobnym do tego w metodzie GetNextIntForClient:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task&lt;int&gt; GetNextInt()
{
    var completionSource = new TaskCompletionSource&lt;int&gt;();

    EventHandler&lt;ResultEventArgs&gt; successHandler = null;
    EventHandler&lt;FailureEventArgs&gt; failureHandler = null;

    successHandler = (sender, args) =&gt;
    {
        _eventApi.GetNextIntCompleted -= successHandler;
        _eventApi.GetNextIntFailed -= failureHandler;
        completionSource.TrySetResult(args.Result);
    };

    failureHandler = (sender, args) =&gt;
    {
        _eventApi.GetNextIntCompleted -= successHandler;
        _eventApi.GetNextIntFailed -= failureHandler;
        completionSource.TrySetException(args.Error);
    };

    _eventApi.GetNextIntCompleted += successHandler;
    _eventApi.GetNextIntFailed += failureHandler;

    _eventApi.GetNextInt();

    return completionSource.Task;
}</pre>
</div>
<p>Sporo kodu&#8230; wypadałoby go skrócić. Napisanie uniwersalnego helpera jest jednak trudniejsze niż się wydaje. Jednym z problemów jest, wspomiany <a href="https://szogun1987.pl/show/Spotkanie-z-TaskCompletionSource-Cz-1-I-promise-I-will-call-back/34">w poprzednim artykule</a>, brak mapowania delegat &#8222;w locie&#8221;. Z moich doświadczeń wynika jednak, że twórcy API zazwyczaj korzystają z typów: EventHandler oraz EventHandler&lt;T&gt;, a nawet jeżeli używają innych typów to są spójni w zakresie swojego API. <a href="https://github.com/szogun1987/events-and-tasks/blob/master/src/Szogun1987.EventsAndTasks/Events/EventToTask.Generic.cs" target="_blank" rel="noopener">Więc całkiem rozsądne okazuje się napisanie klasy będzie zawierać powtarzający się kod</a></p>
<p>sprawi że opakowanie API opartego o eventy w zadania skróci się do:</p>
<div class="code">
<pre class="prettyprint lang-cs">public async Task&lt;int&gt; GetNextIntWithArg(string arg)
{
    var eventToTask = new EventToTask&lt;ResultEventArgs&gt;(
        handler =&gt; _eventApi.GetNextIntCompleted += handler,
        handler =&gt; _eventApi.GetNextIntCompleted -= handler,
        handler =&gt; _eventApi.GetNextIntFailed += handler,
        handler =&gt; _eventApi.GetNextIntFailed -= handler,
        () =&gt; _eventApi.GetNextInt());
    var eventArgs = await eventToTask.Invoke();
    return eventArgs.Result;
}</pre>
</div>
<p>Znacznie lepiej ale dalej fatalnie. Problemem, który widać na pierwszy rzut oka, jest konieczność pisania powtarzalnego kodu w którym łatwo się pomylić. W dodatku w przypadku pomyłki programista nie zostanie ostrzeżony podczas kompilacji, ten błąd może zostać także niezauważony przez długi czas przez wszystkie formy testu i objawić się wyciekiem pamięci albo trudnym do odtworzenia crashem. Drugim problemem, którego nie widać, jest fakt iż kompilator wygeneruje na potrzeby tego kodu 6 klas których obiekty będzie tworzył przy wywołaniu tej metody. Zazwyczaj nie jest to duży problem ale można go łatwo ograniczyć <a href="https://github.com/szogun1987/events-and-tasks/blob/master/src/Szogun1987.EventsAndTasks/Events/EventToTask.Generic2.cs" target="_blank" rel="noopener">zmieniając implementację EventToTask.</a></p>
<p>Użycie wygląda podobnie:</p>
<div class="code">
<pre class="prettyprint lang-cs">var eventToTask = new EventToTask&lt;EventApi, ResultEventArgs&gt;(
    _eventApi,
    (context, handler) =&gt; context.GetNextIntCompleted += handler,
    (context, handler) =&gt; context.GetNextIntCompleted -= handler,
    (context, handler) =&gt; context.GetNextIntFailed += handler,
    (context, handler) =&gt; context.GetNextIntFailed -= handler,
    context =&gt; context.GetNextInt());
    
var eventArgs = await eventToTask.Invoke();
return eventArgs.Result;</pre>
</div>
<p>Sposobem na zwiększenie wykrywalności i zmniejszenie występowania problemów związanych z pomyłkami programisty w tym kodzie wydaje się być użycie klasy Expression. Przykładowy kod jest trochę przy długi zapraszam do zapoznania się znim na <a href="https://github.com/szogun1987/events-and-tasks/tree/master/src/Szogun1987.EventsAndTasks.NonBuilding/Events/EventToTask.cs" target="_blank" rel="noopener">Githubie</a></p>
<p>Użycie tej klasy jest dość proste:</p>
<div class="code">
<pre class="prettyprint lang-cs">var eventToTask = EventToTask
    .Create(_eventApi)
    .WithTrigger(context =&gt; context.GetNextInt())
    .WithResultEvent&lt;ResultEventArgs&gt;((context, handler) =&gt; context.GetNextIntCompleted += handler)
    .WithFailureEvent((context, handler) =&gt; context.GetNextIntFailed += handler)
    .Build();
var eventArgs = await eventToTask.Invoke();
return eventArgs.Result;
</pre>
</div>
<p>jest tylko jeden taki <sub>malutki problemik</sub>: ten kod się nie kompiluje. Niestety parametr typu Expression&lt;T&gt; nie może przyjąć lambdy zawierającej operator +=. Z drugiej strony po za klasą w której zdarzenie jest deklarowane jedynymi dozwolonymi operatorami które mogą go modyfikować są += i -=.</p>
<p>Podsumowując opieranie asynchroniczności o zdarzenia jest zazwyczaj pomyłką architektoniczną i rodzi problemy. Daje się jednak z nią żyć.</p>
<h2>Kody źródłowe</h2>
<p>Kod źródłowy projektu stworzonego na potrzeby tej serii udostępniam na <a href="https://github.com/szogun1987/events-and-tasks">Githubie</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotkanie z TaskCompletionSource &#8211; Cz. 1 I promise I will call back</title>
		<link>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-1-i-promise-i-will-call-back/34/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Thu, 02 Mar 2017 07:55:15 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=34</guid>

					<description><![CDATA[Programowanie asynchroniczne w C# stało całkiem znośne od kiedy język ten posiada słowa kluczowe async i await ... wielu z nas, programistów, jest jednak do dzisiaj zmuszonych pisać asynchronicznie tak jak (nie)potrafi i tak środowisko im na to (nie)pozwala ... Żaden kod napisany przez pierwsze 11 lat istnienia .Net nie miał szans ich użycia. Kod napisany później także niekoniecznie z niego korzysta.


Myślę, że w takiej sytuacji adaptacja starego API na własną rękę może być opłacalna, dlatego postanowiłem popełnić serię artykułów pokazujących jak można się za to zabrać.]]></description>
										<content:encoded><![CDATA[<p>Programowanie asynchroniczne w C# stało całkiem znośne od kiedy język ten posiada słowa kluczowe async i await. Rozwiązanie to tak udało się tak dobrze, że zaczyna pojawiać się w innych językach. VB.Net podobno już je ma (może któryś z czytelników już go używał i mógłby podzielić się swoimi doświadczeniami?), architekci projektujący C++ i Javascript także nad usilnie pracują na wdrożeniem podobnych mechanizmów.</p>
<p><span id="more-34"></span></p>
<p>Wielu z nas, programistów, jest jednak do dzisiaj zmuszonych pisać asynchronicznie tak jak (nie)potrafi i tak środowisko im na to (nie)pozwala. Nawet w C# sytuacja nie wygląda kolorowo, klasa Task umożliwia użycie jej w tandemie z async i await zaledwie od 4 lat. Żaden kod napisany przez pierwsze 11 lat istnienia .Net nie miał szans ich użycia. Kod napisany później także niekoniecznie z niego korzysta.</p>
<p>Myślę, że w takiej sytuacji adaptacja starego API na własną rękę może być opłacalna, dlatego postanowiłem popełnić serię artykułów pokazujących jak można się za to zabrać.<br />
Na szczęście Microsoft szybko zauważył problem adaptacji starego kodu do nowego wzorca, czego efektem jest TaskCompletionSource, który umożliwia przetworzenie czegokolwiek na Task’a.</p>
<p>W pierwszej części chciałbym pokazać adaptację API opartego na kolbakach (ang.callbacks) i obiecankach (ang. Promises).</p>
<p>Wiele angielskich słów nie ma idealnego tłumaczenia, „callback” nie jest tu wyjątkiem. Programiści rozumieją je jako „wywołanie zwrotne”, jednak nikt tak nie mówi, na co dzień używam pięknego słowa „kolbak” i tak będę robił dalej. Dla niewtajemniczonych kolbak opisuje rozwiązanie, w którym metoda jako jeden z argumentów przyjmuje inną metodę, która jest wywoływana po zakończeniu operacji.</p>
<div class="code">
<pre class="prettyprint lang-cs">public void GetNextInt(Action&lt;int&gt; callback)
{
    /* Magic in here */
    callback(123);
}</pre>
</div>
<p>„We will call back to you” w dosłownym tłumaczeniu oznacza „Oddzwonimy do ciebie”. Często to słyszymy, a jak często otrzymujemy telefon gdy coś pójdzie nie tak? I jak się czujemy gdy ktoś długo nie oddzwania? Podobnie czuje się kod i programista, który go napisał, gdy wywołuje metodę z kolbakiem, a ten nigdy nie następuje. Dlatego dobrą praktyką jest przekazanie kodu błędu albo wyjątku jako dodatkowego parametru kolbaka.</p>
<div class="code">
<pre class="prettyprint lang-cs">public void GetNextInt(Action&lt;int, Exception&gt; callback)
{
    try
    {
        /*Magic in here*/
        callback(123, null);
    }
    catch(Exception ex)
    {
        callback(default(int), ex);
    }
}</pre>
</div>
<p>Kolbaki nie są niczym nowym, bo praktycznie każda technologia je wspiera: C++, Javascript, Python, PHP, Java (….aaa nie, przepraszam! Java jednak nie :D), dlatego adaptacja takiej metody do czegoś, co zwróci Taska z wykorzystaniem TaskCompletionSource to nic trudnego.</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt()
{
    var completionSource = new TaskCompletionSource();

    GetNextInt((result, exception) =&gt;
    {
        if (exception != null)
        {
            completionSource.SetException(exception);
        }
        else
        {
            completionSource.SetResult(result);
        }
    });

    return completionSource.Task;
}</pre>
</div>
<p>Taki kod może spowodować przewrócenie się aplikacji. Może się zdarzyć się że callback zostanie wywoływany kilka razy (kompilacja tego nie pilnuje). TaskCompletionSource nie lubi wielokrotnego wywoływania SetException albo SetResult i zgłasza wyjątek. W takim wypadku należy upomnieć twórcę kodu że robi źle, jeżeli to nie pomaga należy użyć środków przymusu bezpośredniego, jak to nie skutkuje należy upewnić się że napisał taki kod ostatni raz. Jeżeli jednak i to jest niemożliwe, ponieważ ktoś już go zdążył zastrzelić należy spróbować zorientować który kolbak jest tym właściwym, jeżeli pierwszy jest dobry wystarczająco to klasa TaskCompletionSource posiada metody TrySetResult i TrySetException, które nie powodują wyjątku przy wielokrotnym wywoływaniu.</p>
<p>Powyższy kod może nie jest może skomplikowany, ale przy pisaniu go 20 raz można się pomylić, dlatego dobrym pomysłem może być napisanie takiego helpera:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task Invoke&lt;T&gt;(Action&lt;T&gt; methodToInvoke)
{
    var completionSource = new TaskCompletionSource&lt;T&gt;();
    methodToInvoke((result, exception) =&gt;
    {
        if (exception != null)
        {
            completionSource.SetException(exception);
        }
        else
        {
            completionSource.SetResult(result);
        }
    });
}</pre>
</div>
<p>Po jego użyciu kod skraca się do:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt()
{
    return Invoke(GetNextInt);
}</pre>
</div>
<p>Kiedy natomiast metoda przyjmuje argumenty:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt(string argument)
{
    return Invoke((handler) =&gt; GetNextInt(argument, handler));
}</pre>
</div>
<p>Użycie takiego helpera ma sens w sytuacji, kiedy API używa typu Action jako callbacka, ale również w memencie kiedy API używa innego typu (wtedy najlepiej jest użyć go do zmiany typu przyjmowanego jako argument helpera).</p>
<p>Problem zaczyna się gdy API używa callbacków różnego typu, ale jak już wspomniełem nasz staruszek C# ma wiele ograniczeń i nie potrafi „w locie” przetłumaczyć typów oznaczanych słowem delegate, nawet jeżeli mają takie same wejścia i wyjścia. Przykładem może być Action&lt;object, eventarg=&#8221;&#8221;&gt; &#8211; nie da się przekazać tej akcji jako EventHandler. W takiej sytuacji można pisać wszystko z palca, napisać generator kodu lub odpuścić i wyciągnąć jakieś wnioski na przyszłość.&lt;/object,&gt;</p>
<h3>Promise (obiecanki-cacanki)</h3>
<p>Obiecanki to bardzo popularny mechanizm używany w wielu technologiac, w .Net raczej nie występuje, gdyż pojawiło się async/await, jednak można spotkać pewne chałupnicze implementacje. Po co jednak słowa – lepiej będzie, gdy spojrzycie na kod, gdyż wyraża on więcej niż tysiąc słów. Jeżeli w aplikacji występuje taki kod:</p>
<div class="code">
<pre class="prettyprint lang-cs">GetNextInt()
    .OnDone(result =&gt; {
        /* Wyświetl wynik */
        MessageBox.Show("Wynik to " + result);
    }).OnError(error =&gt; {
        MessageBox.ShowError("Coś poszło nie tak.")
    }).Always(() =&gt; {
        /* Schowaj kręcioła */
        HideSpinner();
    });</pre>
</div>
<p>to na 99% GetNextInt zwraca Promise ewentualnie Future. Adaptacja Promise do klasy Task jest nawet łatwiejsza niż kolbaka, sami zobaczcie:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Taks&lt;T&gt; Wrap(this IPromise&lt;T&gt; promise)
{
    var taskCompletionSource = new TaskCompletionSource&lt;T&gt;();
    promise
        .OnDone(result =&gt; {
            taskCompletionSource.SetResult(result)
        }).OnError(error =&gt; {
            taskCompletionSource.SetException(error);
        });
    return taskCompletionSource.Task;
}</pre>
</div>
<p>ale może być jeszcze łatwiejsza:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Taks&lt;T&gt; Wrap&lt;T&gt;(this IPromise&lt;T&gt; promise)
{
    var taskCompletionSource = new TaskCompletionSource&lt;T&gt;();
    promise
        .OnDone(taskCompletionSource.SetResult)
        .OnError(taskCompletionSource.SetException);
    return taskCompletionSource.Task;
}</pre>
</div>
<p>Na dziś – tyle. Jednak to jeszce nie koniec … cdn.</p>
<p>Kod źródłowy projektu stworzonego na potrzeby tego postu udostępniam na <a href="https://github.com/szogun1987/events-and-tasks">Githubie</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Uruchamianie asynchronicznych metod bez await &#8211; ogólnie nie polecam</title>
		<link>https://szogun1987.pl/show/uruchamianie-asynchronicznych-metod-bez-await-ogolnie-nie-polecam/33/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Tue, 31 May 2016 20:42:56 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=33</guid>

					<description><![CDATA[Podczas implementowania jedego z ficzer&#243;w aplikacji w pracy popełniłem metodę, w kt&#243;rej uruchomiłem asynchroniczną metodę bez awaita.

]]></description>
										<content:encoded><![CDATA[<p>Podczas implementowania jednego z ficzerów aplikacji w pracy popełniłem metodę, w której uruchomiłem asynchroniczną metodę bez awaita.</p>
<p>Metoda miała i tak być odpalona w trybie &#8222;Fire and forget&#8221; więc uznałem wpisywanie tych kilkunastu znaków za stratę czasu i puściłem moduł na testy, które to testy moduł przeszedł. Jednak w przeciągu tygodnia użytkownicy zaczęli się skarżyć że aplikacja się przewraca w losowych momentach. Logi wskazywały, że mechanizm globalnej obsługi wyjątków loguje błąd o szczegółach podobnych do następujących:</p>
<div style="background: #eee; border: 1px solid #ccc; padding: 5px 10px;">Message:Wyjątków zadania nie zaobserwowano ani przez oczekiwanie na zadanie, ani przez uzyskanie dostępu do jego właściwości Exception. W wyniku tego niezaobserwowany wyjątek został wywołany ponownie przez wątek finalizatora.<br />
Stack trace:</p>
<p>Caused by:</p>
<p>Message:Zgłoszono wyjątek typu 'System.Exception&#8217;.<br />
Stack trace:
</p></div>
<p><span id="more-33"></span></p>
<p>Niewiele da się z tego odczytać. Uratował mnie jednak fakt iż typ wyjątku był mi bardzo dobrze znany (i nie był to System.Exception).<br />
Dodanie awaita sprawiło, że stos zaczął wyglądać po ludzku:</p>
<div style="background: #eee; border: 1px solid #ccc; padding: 5px 10px;">Message:Zgłoszono wyjątek typu 'System.Exception&#8217;.<br />
Stack trace:<br />
w System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)<br />
w System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)<br />
w Szogun1987.TaskExceptions.MainWindow.&lt;WithAwaitAndCompletionSource_Click&gt;d__3.MoveNext() w D:\Projekty\Szogun1987.TaskExceptions\src\Szogun1987.TaskExceptions\Szogun1987.TaskExceptions\MainWindow.xaml.cs:wiersz 30<br />
&#8212; Koniec śladu stosu z poprzedniej lokalizacji, w której wystąpił wyjątek &#8212;<br />
w System.Runtime.CompilerServices.AsyncMethodBuilderCore.&lt;&gt;c.&lt;ThrowAsync&gt;b__6_0(Object state)<br />
w System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)<br />
w System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)</div>
<p>Przygotowałem też programik obrazujący problem: <a href="https://github.com/szogun1987/TaskExceptions">https://github.com/szogun1987/TaskExceptions</a><br />
Błąd wykazuje największą powtarzalność po zbudowaniu w wersji Release. Gdyby błąd nie chciał wystąpić należy wcisnąć przycisk GC.Collect.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Nadmiarowo blokujące się przyciski z MVVM Light</title>
		<link>https://szogun1987.pl/show/nadmiarowo-blokujace-sie-przyciski-z-mvvm-light/32/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 19 Dec 2015 13:51:54 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[MVVMLight]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=32</guid>

					<description><![CDATA[MVVM Light jest biblioteką ułatwiającą tworzenie aplikacji .Net wykorzystujących wzorzec MVVM. Jak do tej pory cieszy się moją sympatią w stopniu znacznie wyższym niż inne frameworki. Głownie dlatego, że nie robi rzeczy o kt&#243;re go nie proszę. Ostatnio jednak znalazłem ciekawe zachowanie tej biblioteki, kt&#243;re może powodować pojawianie się niedeterministycznych bug&#243;w



&#160;

]]></description>
										<content:encoded><![CDATA[<p>MVVM Light jest bilioteką ułatwiającą tworzenie aplikacji wykorzystujących wzorzec MVVM. Jak do tej pory cieszy się moją sympatią w stopniu znacznie wyższym niż inne frameworki. Głownie dlatego, że nie robi rzeczy o które go nie proszę. Ostatnio jednak znalazłem ciekawe zachowanie tej biblioteki, które może powodować pojawianie się niedeterministycznych bugów.<br />
MVMM Light posiada klasę RelayCommand pozwalającą szybko stworzyć pole typu ICommand (<a href="http://www.codeproject.com/Articles/238657/How-to-use-Commands-in-WPF">opis mechanizmu można znaleźć w wielu miejscach w internetach</a>). Klasa ta posiada 2 parametry konstruktora: Execute typu Action &#8211; referencja do metody/lambdy wywoływanej po kliknięciu w przycisk, canExecute typu Func&lt;bool&gt; odwołanie do metody/lambdy wywoływane w celu określenia czy przycisk ma być włączony. Dodatkowo klasa posiada metodę RaiseCanExecuteChanged służącą do informowania przycisku o konieczności ponownego wywołania metody CanExecute.</p>
<p><span id="more-32"></span></p>
<p>Problem, który odkryłem, dotyczy drugiego parametru konstruktora. I aby go lepiej naświetlić przedstawię przypadek użycia, w którym on wystąpił.<br />
Aplikacja posiada ustawienia zapisywane na dysku, które mogą być zmieniane w dedykowanym module. Moduł posiada przyciski &#8222;Zapisz&#8221; i &#8222;Anuluj&#8221; &#8211; pozwalające opuścić moduł. Operacja zapisz zamyka moduł tylko gdy ustawienia przechodzą walidację. Aplikacja na starcie wykrywa czy zapisane ustawienia spełniają te reguły (nie spełniają przy świeżej instalacji oraz jak ktoś usunie plik z dysku), jeżeli nie otwiera moduł ustawień, w tym konkretnym przypadku przycisk anuluj ma być trwale wyłączony. I ten przypadek działał bez zarzutów. Czasami (powtarzalność około 30%) przycisk &#8222;Anuluj&#8221; był wyłączony przy &#8222;ręcznym&#8221; odpaleniu modułu. Błąd dał się odtworzyć na mojej maszynie. Jednak gdy przyjrzałem mu się w trybie Debug zobaczyłem że komenda po wywołaniu CanExecute zawsze zwraca true.</p>
<p><img decoding="async" style="height: 146px; width: 496px;" src="http://static.szogun1987.pl/img/MvvmLight/Debug.png" alt="Podgląd w Visual Studio" /></p>
<p>Jednak przycisk mimo to bywał wyłączony. Błąd wynikał z połączenia kilku czynników. Po pierwsze flagę określającą czy przycisk ma być włączony wyliczałem w konstruktorze i wrzucałem do lambdy w komendzie, nigdzie jej nie przechowując bo nie była mi nigdzie indziej potrzebna. Po drugie referencja do metody przekazanej jako parametr CanExecute w RelayCommand jest przetrzymywana z wykorzystaniem WeakReference i jeżeli znikną wszystkie inne referencje do niej zostanie sprzątnięta przez Garbage Collector. W tym przypadku po wywołaniu metody CanExecute na obiekcie RelayCommand zostanie zwrócona wartość false (asekuracyjnie). Błąd występował jeżeli GC zdążył sprzątnąć moją lambdę zanim została użyta. Jeżeli nie zdążył to moduł działał poprawnie.<br />
Jak rozwiązać ten problem? Po pierwsze można stworzyć własną implementację ICommand nie korzystającą z WeakReference. To rozwiązanie będzie niewątpliwie będzie działać. Problem w tym, że może powodować inne bugi, głównie wycieki pamięci w pewnych skrajnych przypadkach (np. gdy jako parametr przekażemy wyrażenie Lambda wykorzystujące pole statyczne). Po za tym nie po to dodaliśmy MVVM Light żeby rezygnować z jednej z najfajniejszych zabawek. Drugim rozwiązaniem jest powiązanie parametru canExecute z ViewModelem, co sprawi że GC nie posprząta jej tak długo jak ViewModel będzie żył. Można to zrobić przynajmniej na 2 sposoby: w wyrażeniu lambda przekazywanym do RelayCommand użyć przynajmniej 1 pola z klasy (może być to pole ReadOnly) albo jako parametr przekazać niestatyczną metodę z klasy.<br />
Na koniec podaję linka do aplikacji obrazującej błąd: <a href="https://github.com/szogun1987/MvvmLightBugExample">https://github.com/szogun1987/MvvmLightBugExample</a></p>
<p><strong>Edit 27.01.2017:</strong></p>
<p>Do MVVM Light zostało dodane obejście pozwalające naprawić ten błąd. Do konstruktora RelayCommand został dodany parametr &#8222;keepTargetAlive&#8221;. Jeżeli zostanie tam przekazane true błąd przestanie występować.</p>
<p><img decoding="async" class="img-responsive" src="http://static.szogun1987.pl/img/MvvmLight/NewAPI.jpg" alt="" /></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
