BrandonMinnickMBA
6,438 views
30 slides
Aug 30, 2023
Slide 1 of 30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
About This Presentation
Did you know that the .NET compiler turns our async methods into classes? And that .NET adds a try/catch block to each of these classes, potentially hiding thrown exceptions? It's true!
In this session, we will learn how to best use async/await in C# by analyzing how .NET compiles our async cod...
Did you know that the .NET compiler turns our async methods into classes? And that .NET adds a try/catch block to each of these classes, potentially hiding thrown exceptions? It's true!
In this session, we will learn how to best use async/await in C# by analyzing how .NET compiles our async code.
Join me as we take an existing app and optimize its async code together, showing off performance gains, better exception handling, improved run-time speed, smaller app size and more using the latest tools in C#12 + .NET 8!
Size: 13.37 MB
Language: en
Added: Aug 30, 2023
Slides: 30 pages
Slide Content
Correcting Common Async/Await Mistakes Brandon Minnick .NET Developer Advocate
ReadDataFromUrl_MoveNext public void MoveNext () { uint num = ( uint ) this .$PC; this .$PC = -1; try { switch ( num ) { case 0: this .< wc >__0 = new WebClient (); this .$awaiter0 = this .< wc >__0.DownloadDataTaskAsync( this .url ). GetAwaiter (); this .$PC = 1; ... return ; break ; case 1: this .< result >__1 = this .$awaiter0.GetResult(); this .<data>__2 = Encoding.ASCII.GetString ( this .< result >__1); this .$ this.LoadData ( this .<data>__2); break ; default : return ; } } catch ( Exception exception ) { ... } this .$PC = -1; this .$ builder.SetResult (); }
public void MoveNext () { uint num = ( uint ) this .$PC; this .$PC = -1; try { switch ( num ) { case 0: this .< wc >__0 = new WebClient (); this .$awaiter0 = this .< wc >__0.DownloadDataTaskAsync( this .url ). GetAwaiter (); this .$PC = 1; ... return ; break ; case 1: this .< result >__1 = this .$awaiter0.GetResult(); this .<data>__2 = Encoding.ASCII.GetString ( this .< result >__1); this .$ this.LoadData ( this .<data>__2); break ; default : return ; } } catch ( Exception exception ) { ... } this .$PC = -1; this .$ builder.SetResult (); } ReadDataFromUrl_MoveNext case 0: this .< wc >__0 = new WebClient (); this .$awaiter0 = this .< wc >__0.DownloadDataTaskAsync( this .url ). GetAwaiter (); this .$PC = 1; ... return ;
public void MoveNext () { uint num = ( uint ) this .$PC; this .$PC = -1; try { switch ( num ) { case 0: this .< wc >__0 = new WebClient (); this .$awaiter0 = this .< wc >__0.DownloadDataTaskAsync( this .url ). GetAwaiter (); this .$PC = 1; ... return ; break ; case 1: this .< result >__1 = this .$awaiter0.GetResult(); this .<data>__2 = Encoding.ASCII.GetString ( this .< result >__1); this .$ this.LoadData ( this .<data>__2); break ; default : return ; } } catch ( Exception exception ) { ... } this .$PC = -1; this .$ builder.SetResult (); } ReadDataFromUrl_MoveNext case 1: this .< result >__1 = this .$awaiter0.GetResult(); this .<data>__2 = Encoding.ASCII.GetString ( this .< result >__1); this .$ this.LoadData ( this .<data>__2); break ;
public void MoveNext () { uint num = ( uint ) this .$PC; this .$PC = -1; try { switch ( num ) { case 0: this .< wc >__0 = new WebClient (); this .$awaiter0 = this .< wc >__0.DownloadDataTaskAsync( this .url ). GetAwaiter (); this .$PC = 1; ... return ; break ; case 1: this .< result >__1 = this .$awaiter0.GetResult(); this .<data>__2 = Encoding.ASCII.GetString ( this .< result >__1); this .$ this.LoadData ( this .<data>__2); break ; default : return ; } } catch ( Exception exception ) { ... } this .$PC = -1; this .$ builder.SetResult (); } ReadDataFromUrl_MoveNext try { catch ( Exception exception ) { . . . }
Quick Review
Async Keyword Adds 100 Bytes Every Async Method Becomes a Class
Await Every Task Non-awaited Tasks Hide Exceptions
Let’s Fix Some Code
Async/Await Best Practices
Async/Await Best Practices Never Use ` .Wait()` or ` .Result` Always use ` await` If synchronous, use ` . GetAwaiter (). GetResult ()`
Async/Await Best Practices Fire and Forget Tasks Use ` SafeFireAndForget ` NuGet: AsyncAwaitBestPractices
Async/Await Best Practices Avoid ` return await` Remove ` async` keyword Except: In ` try/catch` blocks Except: In ` using( … )` blocks
Async/Await Best Practices Utilize `. ConfigureAwait (false)` Except: When needing to return to calling thread Note: Only works when framework is using SynchronizationContext WPF WinForms Xamarin .NET MAUI WinUI ASP.NET Core
Async/Await Best Practices Utilize ` ValueTask ` When a method’s “hot path” doesn’t call ` await `
Async/Await Best Practices ` IAsyncEnumerable ` for Streaming Data Allows us to update UI as data arrives Better User Experience Use ` [ EnumeratorCancellation ] ` for CancellationToken
Async/Await Best Practices ` . WaitAsync ( CancellationToken )` Append to any async method missing a ` CancellationToken ` parameter
Async/Await Best Practices ` IAsyncDisposable ` The “await” executes at the end of the ` using ` block Can Append ConfigureAwait (false) CancellationToken not currently supported