Asynchroniczność w ASP.NET to temat, który ostatnio przewija się gdzie nie spojrzę. Microsoftowy zespół od ASP.NET kilka miesięcy temu postanowił zatruć życie początkującym programistom tej platformy. Jak to się stało? Otóż w nowej wersji MVC usunęli starą bibliotekę do zarządzania uwierzytelnianiem i autoryzacją użytkowników. Co do samej zmiany nie będę się wdawał w szczegóły - jak wszystko, ma swoje dobre i złe strony. Istotne jest to, że szablon dla nowych aplikacji ASP.NET MVC 5 jest wypchany wywołaniami metod z końcówką Async. Większość tego postu odnosi się do wszystkich aplikacji internetowych, nie tylko ASP.NET, czy innych frameworków .NETowych.

Po co wielowątkowość w aplikacjach internetowych?

Aplikacje internetowe z natury muszą być wielowątkowe. Wyobraźmy sobie sytuację, gdzie do naszego serwera WWW przychodzą równocześnie sto żądań HTTP. Jeżeli nie rozdzielimy obliczeń:

  • nie wykorzystujemy w pełni naszego procesora - po co 8 rdzeni na serwerze, skoro wszystkie obliczenia wykonujemy na jednym?
  • prosimy się o atak odmowy dostępu - nasz system operacyjny nie będzie kolejkował żądań.

Oczywiście developerzy samej aplikacji nie muszą się tym zwykle przejmować. Umieszczając aplikację na serwerze WWW (IIS, Apache etc.) mamy ten problem z głowy. O co więc chodzi z tym wpisem? Kolejkowanie żądań czasem nie wystarczy.

Kiedy powinienem pisać asynchronicznie?

Zasadniczo, powody są trzy:

  1. wykonujesz operację na systemie plików (bazy danych też zwykle trzymane są na dysku),
  2. używasz zdalnego API (np. wrzucasz zdjęcia kotów na Facebooka),
  3. wykonujesz skomplikowane obliczenia, które można zrównoleglić.

Pierwsze dwa przypadki są do siebie podobne - oddajemy obliczenia do innego urządzenia (kontroler dysku, zdalny serwis). Co się wtedy dzieje z naszym wątkiem, w którym obsługujemy żądanie? Nasz wątek czeka. A mógłby robić inne rzeczy… :-)

Asynchroniczność to nie same zalety

Jak się możecie domyślać, wątki też kosztują. Zwykle serwery WWW mają dostępną pulę wątków, dzięki czemu nie musimy ich tworzyć i zabijać. Kosztem jest jednak przełączanie się pomiędzy wątkami, odpowiednia synchronizacja i przekazywanie danych.

Kolejna sprawa - klasyczne programowanie wielowątkowe jest trudne, musimy unikać zakleszczeń. W kolejnych wpisach pokażę, jak .NET 4.5 pozwala uniknąć tego problemu.

Na koniec zostaje perełka, a mianowicie: aplikacja musi być asynchroniczna “all the way”. Co to znaczy? Jeżeli napiszemy asynchroniczne repozytorium (np. do zapisywania danych do BD), to asynchroniczne musi być również wszystko, co wywołuje naszą metodę - serwis, kontroler, framework. W kolejnych wpisach przedstawię jak wygląda obecnie ASP.NET MVC i Entity Framework pod kątem asynchroniczności, a także jak możecie to wykorzystać.