Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
38m 57s
Programowanie asynchroniczne może wydawać się skomplikowane z powodu złożonej terminologii, ale oferuje znaczne korzyści, czyniąc aplikacje szybszymi i bardziej responsywnymi. Film Tima Corey'a na temat "C# Async / Await - Sprawdź, jak zrobić swoją aplikację bardziej responsywną i szybszą dzięki programowaniu asynchronicznemu" oferuje praktyczny przewodnik po skutecznym wykorzystaniu tych funkcji.
W tym artykułe użyjemy dokładnego filmu Tima Corey'a do rozłożenia tych pojęć, prezentując praktyczne zastosowania async i await za pomocą jasnych przykładów. Zajmiemy się różnymi scenariuszami, od asynchronicznych obsług eventów po obsługę wielu zadań, konteksty synchronizacji, obsługę błędów i powszechne pułapki, jak użycie metod async void. Na końcu tego artykułu będziesz miał solidne zrozumienie programowania asynchronicznego i jak je wdrożyć w swoich aplikacjach w C#.
Programowanie asynchroniczne w C# jest kluczowe dla poprawy wydajności aplikacji, szczególnie podczas pracy z operacjami intensywnie wykorzystującymi I/O lub CPU. Slowa kluczowe async i await pozwalaja deweloperom pisac asynchroniczny kod, ktory moze wykonywac dlugotrwale zadania bez blokowania glownego watku. Oznaczajac metode slowem kluczowym async, wskazujesz, ze metoda bedzie wykonywac operacje asynchroniczna, zwracajac zadanie Task lub Task<t>. Slowo kluczowe await jest uzywane w asynchronicznej metodzie, aby wstrzymac wykonanie, az oczekiwane zadanie zostanie ukonczone, co pozwala na rownoczesne wykonywanie innych operacji.
W przeciwieństwie do programowania synchronicznego, w którym zadania wykonują się sekwencyjnie i mogą blokować wątek wywołujący, metody asynchroniczne umożliwiają obsługę wielu zadań jednocześnie, takich jak procesy w tle lub obsługa danych wejściowych od użytkownika, bez zamrażania wątku interfejsu użytkownika. W tym artykule zbadamy, jak async i await wspolpracuja, omawiajac takie pojecia jak metody async void, obsluge bledow, przelaczniki kontekstu i konteksty synchronizacji. Nauczysz się, jak efektywnie zarządzać wieloma operacjami asynchronicznymi i obsługiwać wyjątki, zapewniając płynne wykonanie przez wątek wywołujący, wątek interfejsu użytkownika i zakończenie zadania. To podejście jest szczególnie przydatne w scenariuszach obejmujących systemy plików, żądania sieciowe lub równoczesne żądania, gdzie kluczowa jest responsywność.
Tim wprowadza do programowania asynchronicznego, wyjaśniając różnicę pomiędzy operacjami synchronicznymi a asynchronicznymi. W programowaniu synchronicznym zadania wykonywane są sekwencyjnie, co powoduje opóźnienia, jeśli zadanie trwa długo. Programowanie asynchroniczne pozwala na wykonanie zadań równolegle lub w tle, poprawiając wydajność i responsywność.
Tim wyróżnia dwie główne korzyści programowania asynchronicznego:
Poprawa responsywności interfejsu użytkownika (UI): Wykonywanie zadań asynchronicznie sprawia, że interfejs użytkownika pozostaje responsywny nawet podczas realizacji długotrwałych operacji.
Równoległe wykonanie: Niezależne zadania mogą być wykonywane równolegle, zmniejszając całkowity czas potrzebny na ich zakończenie.
Tim ustawia demo aplikacji Windows Presentation Foundation (WPF), aby pokazać różnicę pomiędzy operacjami synchronicznymi a asynchronicznymi. Aplikacja zawiera dwa przyciski: jeden do wykonywania zadań synchronicznie, a drugi do ich wykonywania asynchronicznie.

Aplikacja zawiera również panel rezultatów do wyświetlania wyników.
Tim wyjaśnia kod stojący za operacją synchroniczną. Stopwatch jest uzywane, aby zmierzyc czas wykonywania zadania.
private void ExecuteSync_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
List<string> websites = GetWebsiteList();
foreach (var website in websites)
{
string result = DownloadWebsite(website);
ReportWebsiteInfo(website, result);
}
stopwatch.Stop();
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}
private List<string> GetWebsiteList()
{
return new List<string>
{
"https://www.yahoo.com",
"https://www.google.com",
"https://www.microsoft.com",
"https://www.cnn.com",
"https://www.codeproject.com",
"https://www.stackoverflow.com"
};
}
private string DownloadWebsite(string websiteURL)
{
WebClient client = new WebClient();
return client.DownloadString(websiteURL);
}
private void ReportWebsiteInfo(string website, string data)
{
ResultsWindow.Text += $"{website}: {data.Length} characters{Environment.NewLine}";
}Private Sub ExecuteSync_Click(sender As Object, e As RoutedEventArgs)
Dim stopwatch As Stopwatch = Stopwatch.StartNew()
Dim websites As List(Of String) = GetWebsiteList()
For Each website In websites
Dim result As String = DownloadWebsite(website)
ReportWebsiteInfo(website, result)
Next
stopwatch.Stop()
ResultsWindow.Text &= $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}"
End Sub
Private Function GetWebsiteList() As List(Of String)
Return New List(Of String) From {
"https://www.yahoo.com",
"https://www.google.com",
"https://www.microsoft.com",
"https://www.cnn.com",
"https://www.codeproject.com",
"https://www.stackoverflow.com"
}
End Function
Private Function DownloadWebsite(websiteURL As String) As String
Dim client As New WebClient()
Return client.DownloadString(websiteURL)
End Function
Private Sub ReportWebsiteInfo(website As String, data As String)
ResultsWindow.Text &= $"{website}: {data.Length} characters{Environment.NewLine}"
End SubTen kod wykonuje następujące kroki:
Tim uruchamia aplikację, aby pokazać operację synchroniczną. Zauważa, że interfejs użytkownika staje się nieodpowiedzialny, gdy strony internetowe są pobierane, a wyniki są wyświetlane wszystkie naraz po zakończeniu pobierania.

Aby zobaczyć praktyczną demonstrację nieporuszającej się formy, obejrzyj film, aby lepiej zrozumieć o 9:20.
Tim radzi sobie z pierwszym problemem, przekształcając metodę synchroniczną w asynchroniczną. To wymaga uzycia slow kluczowych async i await. Oto szczegółowy przedstawienie procesu:
Skopiowanie Istniejącej Metody Synchronicznej:
private async Task RunDownloadAsync()
{
// Same code as RunDownloadSync, but will be modified for async
}
Modyfikacja Wywołania Pobierania dla Asynchronicznego Wykonania:
Task.Run, aby wykonac je asynchronicznie.private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
{
return await Task.Run(() => DownloadWebsite(websiteURL));
}
await zapewnia, ze metoda czeka na zakonczenie asynchronicznego zadania przed kontynuowaniem.Upewnij Się, że Metoda Jest Async:
async i zwraca zadanie Task.private async Task RunDownloadAsync()
{
List<string> websites = GetWebsiteList();
foreach (var website in websites)
{
var result = await DownloadWebsiteAsync(website);
ReportWebsiteInfo(website, result);
}
}
Poprawna Obsługa Zdarzenia:
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
await RunDownloadAsync();
stopwatch.Stop();
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}
Tim pokazuje, ze uzywajac slowa kluczowego await, interfejs uzytkownika pozostaje responsywny. To pozwala uzytkownikom na interakcje z oknem, gdy asynchroniczne zadanie jest uruchomione.
// UI remains responsive
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
await RunDownloadAsync();
stopwatch.Stop();
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}' UI remains responsive
Private Async Sub ExecuteAsync_Click(sender As Object, e As RoutedEventArgs)
Dim stopwatch As Stopwatch = Stopwatch.StartNew()
Await RunDownloadAsync()
stopwatch.Stop()
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}"
End SubAby upewnic sie, ze calkowity czas wykonania jest poprawnie raportowany, Tim dodaje slowo kluczowe await do wywolania w obslugiwaniu zdarzenia klikniecia przycisku.
// Correctly waits for the asynchronous task to complete
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
await RunDownloadAsync();
stopwatch.Stop();
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}' Correctly waits for the asynchronous task to complete
Private Async Sub ExecuteAsync_Click(sender As Object, e As RoutedEventArgs)
Dim stopwatch As Stopwatch = Stopwatch.StartNew()
Await RunDownloadAsync()
stopwatch.Stop()
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}"
End SubCzekając na zakończenie metody asynchronicznej, czas wykonania jest mierzony dokładnie, a wyniki są wyświetlane tak, jak są pobierane.
Tim odnosi się do ograniczenia czekania na zakończenie każdej z sekwencyjnie wykonywanych zadań, wykorzystując wykonanie równoległe. Oto jak zmodyfikował kod, aby to osiągnąć:
Skopiowanie Istniejącej Metody Async:
private async Task RunDownloadParallelAsync()
{
// Parallel execution logic will be added here
}
Utworzenie Listy Zadań:
List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();Dim tasks As New List(Of Task(Of WebsiteDataModel))()Rozpoczęcie Wszystkich Zadań Bez Oczekiwania:
foreach (var website in websites)
{
tasks.Add(DownloadWebsiteAsync(website));
}
Czekanie Na Zakończenie Wszystkich Zadań:
Task.WhenAll jest uzywana do oczekiwania na zakonczenie wszystkich zadan. Metoda ta zwraca tablicę wyników, gdy wszystkie zadania są zakończone.WebsiteDataModel[] results = await Task.WhenAll(tasks);Dim results As WebsiteDataModel() = Await Task.WhenAll(tasks)Przetwarzanie Wyników:
foreach (var result in results)
{
ReportWebsiteInfo(result);
}
Oto kompletny kod dla metody wykonania równoległego:
private async Task RunDownloadParallelAsync()
{
List<string> websites = GetWebsiteList();
List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
foreach (var website in websites)
{
tasks.Add(DownloadWebsiteAsync(website));
}
WebsiteDataModel[] results = await Task.WhenAll(tasks);
foreach (var result in results)
{
ReportWebsiteInfo(result);
}
}Private Async Function RunDownloadParallelAsync() As Task
Dim websites As List(Of String) = GetWebsiteList()
Dim tasks As New List(Of Task(Of WebsiteDataModel))()
For Each website As String In websites
tasks.Add(DownloadWebsiteAsync(website))
Next
Dim results As WebsiteDataModel() = Await Task.WhenAll(tasks)
For Each result As WebsiteDataModel In results
ReportWebsiteInfo(result)
Next
End FunctionTim aktualizuje obsługę kliknięcia przycisku, aby wywołać nową metodę wykonania równoległego.
private async void ExecuteAsync_Click(object sender, RoutedEventArgs e)
{
Stopwatch stopwatch = Stopwatch.StartNew();
await RunDownloadParallelAsync();
stopwatch.Stop();
ResultsWindow.Text += $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}";
}Private Async Sub ExecuteAsync_Click(sender As Object, e As RoutedEventArgs)
Dim stopwatch As Stopwatch = Stopwatch.StartNew()
Await RunDownloadParallelAsync()
stopwatch.Stop()
ResultsWindow.Text &= $"Total execution time: {stopwatch.ElapsedMilliseconds} ms{Environment.NewLine}"
End SubCzekajac na RunDownloadParallelAsync, calkowity czas wykonania jest dokladnie mierzony i raportowany.
Tim demonstruje poprawę wydajności, uruchamiając aplikację z wykonaniem równoległym. Wyniki pokazują znaczącą redukcję całkowitego czasu wykonania w porównaniu do wykonania sekwencyjnego.
// Parallel execution
async Task RunDownloadParallelAsync();' Parallel execution
Async Function RunDownloadParallelAsync() As Task
End FunctionPrzyspieszenie jest widoczne, gdy strony internetowe są pobierane równocześnie, zmniejszając całkowity czas oczekiwania do czasu trwania najwolniejszego indywidualnego pobrania.
Task.Run() vs Asynchroniczne wywolanie metodyTim wyjasnia koncepcje uzycia Task.Run() do owiniecia synchronicznej metody i uczynienia jej asynchroniczna, gdy nie mozna zmodyfikowac oryginalnej metody. Jednakże, pokazuje również preferowane podejście modyfikacji samej metody, aby była asynchroniczna, jeśli masz nad nią kontrolę.
Owijanie metody w Task.Run():
private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
{
return await Task.Run(() => DownloadWebsite(websiteURL));
}
Uczynienie Metody Asynchroniczną:
Jeśli możesz zmodyfikować metodę, lepiej jest przekonwertować samą metodę na asynchroniczną, używając odpowiedniego API asynchronicznego.
Tim demonstruje to, zmieniajac DownloadWebsite na DownloadWebsiteAsync i uzywajac DownloadStringTaskAsync z WebClient.
private async Task<WebsiteDataModel> DownloadWebsiteAsync(string websiteURL)
{
WebClient client = new WebClient();
string data = await client.DownloadStringTaskAsync(websiteURL);
return new WebsiteDataModel { URL = websiteURL, Data = data };
}
Dostosowanie Metody Wywołującej:
Task.Run() i bezposrednio wywolac metode asynchroniczna.private async Task RunDownloadParallelAsync()
{
List<string> websites = GetWebsiteList();
List<Task<WebsiteDataModel>> tasks = new List<Task<WebsiteDataModel>>();
foreach (var website in websites)
{
tasks.Add(DownloadWebsiteAsync(website));
}
WebsiteDataModel[] results = await Task.WhenAll(tasks);
foreach (var result in results)
{
ReportWebsiteInfo(result);
}
}Private Async Function RunDownloadParallelAsync() As Task
Dim websites As List(Of String) = GetWebsiteList()
Dim tasks As New List(Of Task(Of WebsiteDataModel))()
For Each website As String In websites
tasks.Add(DownloadWebsiteAsync(website))
Next
Dim results As WebsiteDataModel() = Await Task.WhenAll(tasks)
For Each result As WebsiteDataModel In results
ReportWebsiteInfo(result)
Next
End FunctionTim kończy z kilkoma ważnymi wskazówkami dotyczącymi użycia async i await:
Zapewnij metody zwracajace zadania: Kiedykolwiek oznaczasz metode jako async, powinna zwracac Task lub Task<t> zamiast void (z wyjatkiem obslug zdarzen).
Uzyj await do niezawodnych operacji: Uzywaj slowa kluczowego await, gdy potrzebujesz wynikow asynchronicznej operacji przed kontynuowaniem.
Owijanie zadania dla niemodyfikowalnego kodu: Uzyj Task.Run() do owijania synchronicznych metod, gdy nie mozna zmodyfikowac oryginalnej metody.
Odpowiednio oznacz metody async: Zawsze dodawaj Async do nazwy metody, aby wskazac, ze jest to operacja asynchroniczna.
Wykonanie Równoległe vs Sekwencyjne: Zdecyduj, czy zadania mogą być wykonywane równolegle, czy powinny czekać na siebie nawzajem, w oparciu o zależności między zadaniami.
Tim podkresla, ze programowanie asynchroniczne w C# zostalo uproszczone dzieki async, await i Task. Złożoności takie jak konteksty wątków i modele apartamentów są zarządzane w tle.
Samouczek Tima Corey'a na temat async i await w C# stanowi niezastąpione źródło do opanowania programowania asynchronicznego. Dokładnie wyjaśniając pojęcia takie jak równoległość zadań, responsywność interfejsu użytkownika oraz znaczenie używania async i await w odpowiednim kontekście, Tim dostarcza programistom narzędzi do tworzenia szybszych i bardziej responsywnych aplikacji. Jego szczegółowy przechodzenie pokazuje, jak efektywnie obsługiwać długotrwałe zadania bez blokowania głównego wątku, oraz strategie zarządzania operacjami asynchronicznymi i równoległym wykonaniem.
Aby uzyskać głębsze zrozumienie i dodatkowe praktyczne przykłady, gorąco polecam obejrzenie filmu Tima Corey'a video. Jego spostrzeżenia na temat metod async void, obsługi błędów i zarządzania kontekstami synchronizacji dodatkowo zwiększą twoją zdolność do wdrożenia tych pojęć w swoich projektach.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy