Zdarzenia
Power BI DataViz World Championships
14 lut, 16 - 31 mar, 16
Z 4 szans na wejście, można wygrać pakiet konferencji i zrobić go do LIVE Grand Finale w Las Vegas
Dowiedz się więcejTa przeglądarka nie jest już obsługiwana.
Przejdź na przeglądarkę Microsoft Edge, aby korzystać z najnowszych funkcji, aktualizacji zabezpieczeń i pomocy technicznej.
Autor : Rick Anderson
Ten samouczek zawiera podstawowe informacje na temat tworzenia asynchronicznej aplikacji internetowej MVC ASP.NET przy użyciu Visual Studio Express 2012 for Web, która jest bezpłatną wersją programu Microsoft Visual Studio. Możesz również użyć programu Visual Studio 2012.
Kompletny przykład został udostępniony na potrzeby tego samouczka w witrynie GitHub https://github.com/RickAndMSFT/Async-ASP.NET/
Klasa kontrolerów MVC 4 ASP.NET w połączeniu .NET 4.5 umożliwia zapisywanie asynchronicznych metod akcji, które zwracają obiekt typu Akcja zadaniaResult<>. W .NET Framework 4 wprowadzono asynchroniczne pojęcie programowania nazywane zadaniem i ASP.NET MVC 4 obsługuje zadanie. Zadania są reprezentowane przez typ zadania i powiązane typy w przestrzeni nazw System.Threading.Tasks . .NET Framework 4.5 opiera się na tej asynchronicznej obsłudze słów kluczowych await i asynchronicznych, które sprawiają, że praca z obiektami zadań jest znacznie mniej złożona niż poprzednie podejścia asynchroniczne. Słowo kluczowe await to skrót składniowy wskazujący, że fragment kodu powinien asynchronicznie czekać na inny fragment kodu. Słowo kluczowe asynchroniczne reprezentuje wskazówkę, której można użyć do oznaczania metod jako metod asynchronicznych opartych na zadaniach. Kombinacja funkcji await, asynchronicznego i obiektu Task znacznie ułatwia pisanie kodu asynchronicznego na platformie .NET 4.5. Nowy model metod asynchronicznych jest nazywany asynchronicznym wzorcem asynchronicznym opartym na zadaniach (TAP). W tym samouczku założono, że masz pewną znajomość programowania asynchronicznego przy użyciu słów kluczowych await i asynchronicznych oraz przestrzeni nazw Zadania .
Aby uzyskać więcej informacji na temat używania słów kluczowych await i asynchronicznych oraz przestrzeni nazw zadania , zobacz następujące odwołania.
Na serwerze internetowym .NET Framework obsługuje pulę wątków używanych do obsługi żądań ASP.NET. Po odebraniu żądania jest wysyłany wątek z puli w celu przetworzenia tego żądania. Jeśli żądanie jest przetwarzane synchronicznie, wątek, który przetwarza żądanie, jest zajęty podczas przetwarzania żądania, a ten wątek nie może obsłużyć innego żądania.
Może to nie być problem, ponieważ pula wątków może być wystarczająco duża, aby pomieścić wiele zajętych wątków. Jednak liczba wątków w puli wątków jest ograniczona (wartość domyślna maksymalna dla platformy .NET 4.5 to 5000). W dużych aplikacjach z wysoką współbieżnością długotrwałych żądań wszystkie dostępne wątki mogą być zajęte. Ten warunek jest nazywany głodem wątku. Po osiągnięciu tego warunku serwer internetowy kolejkuje żądania. Jeśli kolejka żądań stanie się pełna, serwer internetowy odrzuca żądania ze stanem HTTP 503 (Serwer jest zbyt zajęty). Pula wątków CLR ma ograniczenia dotyczące iniekcji nowego wątku. Jeśli współbieżność jest pęknięta (oznacza to, że witryna internetowa może nagle uzyskać dużą liczbę żądań), a wszystkie dostępne wątki żądań są zajęte z powodu wywołań zaplecza z dużym opóźnieniem, ograniczona szybkość iniekcji wątku może sprawić, że aplikacja będzie reagować bardzo źle. Ponadto każdy nowy wątek dodany do puli wątków ma narzut (na przykład 1 MB pamięci stosu). Aplikacja internetowa korzystająca z metod synchronicznych do obsługi wywołań o dużym opóźnieniu, w których pula wątków zwiększa się do domyślnego maksymalnie 5,000 wątków platformy .NET 4.5, 000 wątków zużywałoby około 5 GB więcej pamięci niż aplikacja mogła obsługiwać te same żądania przy użyciu metod asynchronicznych i tylko 50 wątków. Podczas wykonywania pracy asynchronicznej nie zawsze używasz wątku. Na przykład po utworzeniu asynchronicznego żądania usługi internetowej ASP.NET nie będzie używać żadnych wątków między wywołaniem metody asynchronicznej a await. Użycie puli wątków do żądań obsługi z dużym opóźnieniem może prowadzić do dużego zużycia pamięci i słabego wykorzystania sprzętu serwera.
W aplikacji internetowej, która widzi dużą liczbę współbieżnych żądań podczas uruchamiania lub ma zwiększone obciążenie (w przypadku nagłego wzrostu współbieżności), wykonywanie asynchronicznych wywołań usług internetowych zwiększa czas odpowiedzi aplikacji. Żądanie asynchroniczne trwa tyle samo czasu, aby przetwarzać je jako żądanie synchroniczne. Jeśli żądanie wykonuje wywołanie usługi internetowej, które wymaga dwóch sekund do ukończenia, żądanie trwa dwie sekundy, niezależnie od tego, czy jest wykonywane synchronicznie, czy asynchronicznie. Jednak podczas wywołania asynchronicznego wątek nie może odpowiadać na inne żądania, czekając na ukończenie pierwszego żądania. W związku z tym żądania asynchroniczne uniemożliwiają kolejkowanie żądań i wzrost puli wątków, gdy istnieje wiele współbieżnych żądań, które wywołują długotrwałe operacje.
W tej sekcji wymieniono wskazówki dotyczące używania metod akcji synchronicznych lub asynchronicznych. Są to tylko wytyczne; zbadaj każdą aplikację indywidualnie, aby określić, czy metody asynchroniczne pomagają w wydajności.
Ogólnie rzecz biorąc, użyj metod synchronicznych dla następujących warunków:
Ogólnie rzecz biorąc, użyj metod asynchronicznych dla następujących warunków:
W przykładzie do pobrania pokazano, jak efektywnie używać metod akcji asynchronicznych. Udostępniony przykład został zaprojektowany w celu zapewnienia prostego pokazu programowania asynchronicznego w ASP.NET MVC 4 przy użyciu platformy .NET 4.5. Przykład nie jest przeznaczony do architektury referencyjnej programowania asynchronicznego w ASP.NET MVC. Przykładowy program wywołuje metody internetowego interfejsu API ASP.NET , które z kolei wywołają metodę Task.Delay w celu symulowania długotrwałych wywołań usług internetowych. Większość aplikacji produkcyjnych nie pokaże takich oczywistych korzyści z używania metod akcji asynchronicznych.
W przypadku kilku aplikacji wszystkie metody akcji muszą być asynchroniczne. Często konwertowanie kilku synchronicznych metod akcji na metody asynchroniczne zapewnia najlepszy wzrost wydajności dla wymaganej ilości pracy.
Przykładową aplikację można pobrać z https://github.com/RickAndMSFT/Async-ASP.NET/ witryny GitHub . Repozytorium składa się z trzech projektów:
Products, Gizmos and Widgets
API MVC 4 ASP.NET implementujący kontrolery. Udostępnia ona dane dla projektu WebAppAsync i projektu Mvc4Async .Poniższy kod przedstawia Gizmos
synchroniczną metodę akcji używaną do wyświetlania listy gizmos. (W tym artykule gizmo jest fikcyjnym urządzeniem mechanicznym).
public ActionResult Gizmos()
{
ViewBag.SyncOrAsync = "Synchronous";
var gizmoService = new GizmoService();
return View("Gizmos", gizmoService.GetGizmos());
}
Poniższy kod przedstawia metodę GetGizmos
usługi gizmo.
public class GizmoService
{
public async Task<List<Gizmo>> GetGizmosAsync(
// Implementation removed.
public List<Gizmo> GetGizmos()
{
var uri = Util.getServiceUri("Gizmos");
using (WebClient webClient = new WebClient())
{
return JsonConvert.DeserializeObject<List<Gizmo>>(
webClient.DownloadString(uri)
);
}
}
}
Metoda GizmoService GetGizmos
przekazuje identyfikator URI do usługi HTTP internetowego interfejsu API ASP.NET, która zwraca listę danych gizmos. Projekt WebAPIpgw zawiera implementację internetowego interfejsu API gizmos, widget
i product
kontrolerów.
Na poniższej ilustracji przedstawiono widok gizmos z przykładowego projektu.
W przykładzie użyto nowych słów kluczowych asynchronicznych i await (dostępnych w programach .NET 4.5 i Visual Studio 2012), aby umożliwić kompilatorowi zachowanie skomplikowanych przekształceń niezbędnych do programowania asynchronicznego. Kompilator umożliwia pisanie kodu przy użyciu synchronicznych konstrukcji przepływu sterowania języka C#, a kompilator automatycznie stosuje przekształcenia niezbędne do używania wywołań zwrotnych w celu uniknięcia blokowania wątków.
Poniższy kod przedstawia metodę Gizmos
synchroniczną i metodę GizmosAsync
asynchroniczną. Jeśli przeglądarka obsługuje element HTML 5<mark>
, zmiany zostaną wyświetlone w GizmosAsync
żółtym wyróżnieniu.
public ActionResult Gizmos()
{
ViewBag.SyncOrAsync = "Synchronous";
var gizmoService = new GizmoService();
return View("Gizmos", gizmoService.GetGizmos());
}
public async Task<ActionResult> GizmosAsync()
{
ViewBag.SyncOrAsync = "Asynchronous";
var gizmoService = new GizmoService();
return View("Gizmos", await gizmoService.GetGizmosAsync());
}
Następujące zmiany zostały zastosowane w celu umożliwienia GizmosAsync
asynchronicznego elementu .
Task<ActionResult>
zwracanego elementu.ActionResult
na Task<ActionResult>
. Zwracany Task<ActionResult>
typ reprezentuje bieżącą pracę i udostępnia wywołania metody z uchwytem, za pomocą którego należy czekać na zakończenie operacji asynchronicznej. W takim przypadku obiekt wywołujący jest usługą internetową. Task<ActionResult>
reprezentuje bieżącą pracę z wynikiem ActionResult.
GetGizmosAsync
).GetGizmosAsync
Wewnątrz treści metody wywoływana jest inna metoda GetGizmosAsync
asynchroniczna. GetGizmosAsync
natychmiast zwraca element Task<List<Gizmo>>
, który zostanie ostatecznie ukończony po udostępnieniu danych. Ponieważ nie chcesz robić nic innego, dopóki nie masz danych gizmo, kod czeka na zadanie (przy użyciu słowa kluczowego await ). Słowo kluczowe await można używać tylko w metodach z adnotacjami ze słowem kluczowym asynchronicznego .
Słowo kluczowe await nie blokuje wątku do momentu ukończenia zadania. Spowoduje to zarejestrowanie pozostałej części metody jako wywołania zwrotnego w zadaniu i natychmiastowe zwrócenie. Po zakończeniu oczekiwanego zadania wywołanie zwrotne wywołania zwrotnego spowoduje wznowienie wykonywania metody w prawo od lewej. Aby uzyskać więcej informacji na temat używania słów kluczowych await i asynchronicznych oraz przestrzeni nazw zadań , zobacz odwołania asynchroniczne.
W poniższym kodzie przedstawiono metody GetGizmos
i GetGizmosAsync
.
public List<Gizmo> GetGizmos()
{
var uri = Util.getServiceUri("Gizmos");
using (WebClient webClient = new WebClient())
{
return JsonConvert.DeserializeObject<List<Gizmo>>(
webClient.DownloadString(uri)
);
}
}
public async Task<List<Gizmo>> GetGizmosAsync()
{
var uri = Util.getServiceUri("Gizmos");
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri);
return (await response.Content.ReadAsAsync<List<Gizmo>>());
}
}
Zmiany asynchroniczne są podobne do zmian wprowadzonych w powyższej konfiguracji GizmosAsync .
Task<List<Gizmo>>
, a Async został dołączony do nazwy metody.Na poniższej ilustracji przedstawiono asynchroniczny widok gizmo.
Prezentacja przeglądarki danych gizmos jest identyczna z widokiem utworzonym przez wywołanie synchroniczne. Jedyna różnica polega na tym, że wersja asynchroniczna może być bardziej wydajna w przypadku ciężkich obciążeń.
Metody akcji asynchronicznych mają znaczącą przewagę nad metodami synchronicznymi, gdy akcja musi wykonywać kilka niezależnych operacji. W podanym przykładzie metoda PWG
synchroniczna (w przypadku produktów, widżetów i Gizmos) wyświetla wyniki trzech wywołań usługi internetowej, aby uzyskać listę produktów, widżetów i gizmos. Projekt internetowego interfejsu API ASP.NET , który udostępnia te usługi, używa funkcji Task.Delay do symulowania opóźnienia lub wolnych wywołań sieciowych. Gdy opóźnienie jest ustawione na 500 milisekund, metoda asynchroniczna zajmuje nieco ponad 500 milisekund do ukończenia, podczas gdy wersja synchroniczna PWGasync
PWG
przejmuje 1500 milisekund. Metoda synchroniczna PWG
jest wyświetlana w poniższym kodzie.
public ActionResult PWG()
{
ViewBag.SyncType = "Synchronous";
var widgetService = new WidgetService();
var prodService = new ProductService();
var gizmoService = new GizmoService();
var pwgVM = new ProdGizWidgetVM(
widgetService.GetWidgets(),
prodService.GetProducts(),
gizmoService.GetGizmos()
);
return View("PWG", pwgVM);
}
Metoda asynchroniczna PWGasync
jest wyświetlana w poniższym kodzie.
public async Task<ActionResult> PWGasync()
{
ViewBag.SyncType = "Asynchronous";
var widgetService = new WidgetService();
var prodService = new ProductService();
var gizmoService = new GizmoService();
var widgetTask = widgetService.GetWidgetsAsync();
var prodTask = prodService.GetProductsAsync();
var gizmoTask = gizmoService.GetGizmosAsync();
await Task.WhenAll(widgetTask, prodTask, gizmoTask);
var pwgVM = new ProdGizWidgetVM(
widgetTask.Result,
prodTask.Result,
gizmoTask.Result
);
return View("PWG", pwgVM);
}
Na poniższej ilustracji przedstawiono widok zwrócony z metody PWGasync .
Metody akcji asynchronicznej zwracane Task<ActionResult>
są do anulowania, czyli przyjmują parametr CancelToken , gdy jest dostarczany z atrybutem AsyncTimeout . Poniższy kod przedstawia metodę GizmosCancelAsync
z limitem czasu 150 milisekund.
[AsyncTimeout(150)]
[HandleError(ExceptionType = typeof(TimeoutException),
View = "TimeoutError")]
public async Task<ActionResult> GizmosCancelAsync(
CancellationToken cancellationToken )
{
ViewBag.SyncOrAsync = "Asynchronous";
var gizmoService = new GizmoService();
return View("Gizmos",
await gizmoService.GetGizmosAsync(cancellationToken));
}
Poniższy kod przedstawia przeciążenie GetGizmosAsync, które przyjmuje parametr CancellationToken .
public async Task<List<Gizmo>> GetGizmosAsync(string uri,
CancellationToken cancelToken = default(CancellationToken))
{
using (HttpClient httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(uri, cancelToken);
return (await response.Content.ReadAsAsync<List<Gizmo>>());
}
}
W podanej przykładowej aplikacji wybranie linku Pokaz tokenu anulowania wywołuje metodę GizmosCancelAsync
i demonstruje anulowanie wywołania asynchronicznego.
Aby zrealizować korzyści wynikające z asynchronicznej aplikacji internetowej, może być konieczne wprowadzenie pewnych zmian w domyślnej konfiguracji serwera. Pamiętaj o następujących kwestiach podczas konfigurowania i testowania obciążenia aplikacji internetowej asynchronicznej.
Systemy Windows 7, Windows Vista i wszystkie systemy operacyjne klienckie systemu Windows mają maksymalnie 10 współbieżnych żądań. Potrzebujesz systemu operacyjnego Windows Server, aby zobaczyć zalety metod asynchronicznych pod dużym obciążeniem.
Zarejestruj program .NET 4.5 w usługach IIS w wierszu polecenia z podwyższonym poziomem uprawnień:
%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis -i
Zobacz ASP.NET narzędzie rejestracji usług IIS (Aspnet_regiis.exe)
Może być konieczne zwiększenie limitu kolejkiHTTP.sys z wartości domyślnej 1000 do 5000. Jeśli ustawienie jest zbyt niskie, może zostać wyświetlone HTTP.sys odrzucanie żądań ze stanem HTTP 503. Aby zmienić limit kolejki HTTP.sys:
Uwaga na powyższych obrazach platforma .NET Framework jest wyświetlana jako wersja 4.0, mimo że pula aplikacji korzysta z platformy .NET 4.5. Aby zrozumieć tę rozbieżność, zobacz następujące kwestie:
Jeśli aplikacja korzysta z usług internetowych lub System.NET do komunikowania się z zapleczem za pośrednictwem protokołu HTTP, może być konieczne zwiększenie elementu connectionManagement/maxconnection . W przypadku aplikacji ASP.NET jest to ograniczone przez funkcję autokonfiguracji do 12 razy więcej procesorów CPU. Oznacza to, że w quad-proc można mieć co najwyżej 12 * 4 = 48 współbieżnych połączeń z punktem końcowym adresu IP. Ponieważ jest to powiązane z autoConfig, najprostszym sposobem zwiększenia maxconnection
ASP.NET aplikacji jest ustawienie parametru System.Net.ServicePointManager.DefaultConnectionLimit programowo w metodzie from Application_Start
w pliku global.asax . Zobacz przykład pobierania przykładu.
W programie .NET 4.5 wartość domyślna 5000 dla parametru MaxConcurrentRequestsPerCPU powinna być odpowiednia.
Zdarzenia
Power BI DataViz World Championships
14 lut, 16 - 31 mar, 16
Z 4 szans na wejście, można wygrać pakiet konferencji i zrobić go do LIVE Grand Finale w Las Vegas
Dowiedz się więcejSzkolenie
Ścieżka szkoleniowa
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization