async-await best practices in 10 minutes

37
50ª Reunião Presencial @ LISBOA DateTime.Parse(“22-11-2014", new CultureInfo("pt-PT")); http://netpont o.org hashtag #netponto

Upload: paulo-morgado

Post on 22-Aug-2015

860 views

Category:

Documents


11 download

TRANSCRIPT

Page 1: Async-await best practices in 10 minutes

50ª Reunião Presencial @ LISBOADateTime.Parse(“22-11-2014", new CultureInfo("pt-PT"));

http://netponto.org

hashtag #netponto

Page 2: Async-await best practices in 10 minutes

Async-Await Best Practincesin 10 minutes

Paulo Morgado

http://netponto.org50ª Reunião Lisboa – 22-11-2014

Page 3: Async-await best practices in 10 minutes

Paulo Morgado• http://PauloMorgado.NET/• @PauloMorgado• http://about.me/PauloMorgado• http://www.slideshare.net/PauloJorgeMorgado• http://pontonetpt.org/blogs/paulomorgado/• http://blogs.msmvps.com/paulomorgado/• http://weblogs.asp.net/paulomorgado• http://www.revista-programar.info/author/pmorgad

o/

Page 4: Async-await best practices in 10 minutes

For goodness’ sake,stop using async void!

Page 5: Async-await best practices in 10 minutes

Async void is only for event handlersPrinciplesAsync void is a “fire-and-forget” mechanism...The caller is unable to know when an async void has finishedThe caller is unable to catch exceptions thrown from an async void

(instead they get posted to the UI message-loop)

GuidanceUse async void methods only for top-level event handlers (and their like)Use async Task-returning methods everywhere elseIf you need fire-and-forget elsewhere, indicate it explicitly e.g. “FredAsync().FireAndForget()”When you see an async lambda, verify it

Page 6: Async-await best practices in 10 minutes

The problem is events.They’re not going away.

Page 7: Async-await best practices in 10 minutes

Async over events• Principles

Callback-based programming, as with events, is hard

• GuidanceIf the event-handlers are largely independent, then leave them as eventsBut if they look like a state-machine, then await is sometimes easierTo turn events into awaitable Tasks, use TaskCompletionSource

Page 8: Async-await best practices in 10 minutes

Is it CPU-bound,or I/O-bound?

Page 9: Async-await best practices in 10 minutes

ThreadpoolPrinciplesCPU-bound work means things like: LINQ-over-objects, or big iterations, or computational inner loops.Parallel.ForEach and Task.Run are a good way to put CPU-bound work onto the thread pool.Thread pool will gradually feel out how many threads are needed to make best progress.Use of threads will never increase throughput on a machine that’s under load.

GuidanceFor IO-bound “work”, use await rather than background threads.For CPU-bound work, consider using background threads via Parallel.ForEach or Task.Run, unless you're writing a library, or scalable server-side code.

Page 10: Async-await best practices in 10 minutes

Don’t lie

Page 11: Async-await best practices in 10 minutes

Two ways of thinking about asynchrony

• Foo();• Perform something here and now.• I’ll regain control to execute

something else when it’s done.

• var task = FooAsync();• Initiate something here and now.• I’ll regain control to execute

something else “immediately”.

From the method signature (how people call it)

Uses a CPU core solidly while it runs

void Foo(){ for (int i=0; i<100; i++) Math.Sin(i);}

From the method implementation (what resources it uses) Hardly touches the CPU

async Task FooAsync(){ await client.DownloadAsync();}

Page 12: Async-await best practices in 10 minutes

Async methods: Your caller’s assumptions“This method’s name ends with ‘Async’, so…”

“…calling it won’t spawn new threads in my server app”

“…I can parallelize by simply calling it multiple times”

Is this true for your async methods?

Page 13: Async-await best practices in 10 minutes

Libraries generally shouldn’t use Task.Run()

Page 14: Async-await best practices in 10 minutes

Your callers should be the ones to call Task.Run“await task;”Captures the current SyncContext before awaiting.When it resumes, uses SyncContext.Post() to resume “in the same place”(If SyncContext is null, uses the TaskScheduler)

For application-level code:This behavior is almost always what you want.

For library-level code:This behavior is rarely what you want!

Page 15: Async-await best practices in 10 minutes

Sync methods: Your caller’s assumptions“There’s a synchronous version of this method…”

“…I guess it must be faster than the async version”

“…I can call it from the UI thread if the latency’s fine”

void Foo() { FooAsync().Wait(); } -- will deadlock!!!

Page 16: Async-await best practices in 10 minutes

Library methods shouldn't liePrinciplesIn a server app, spinning up threads hurts scalabilty.The app (not the library) is in the best position to manage its own threads.Users will assume they know your method's implementation by looking at its signature.

GuidanceDefine an async signature “FooAsync” when your implementation is truly async.Define a sync signature "Foo" when your implementation is fast and won't deadlock.Don't use blocking calls to Wait() .Result in libraries; that invites deadlocks.

Page 17: Async-await best practices in 10 minutes

Use ConfigureAwait(false)

Page 18: Async-await best practices in 10 minutes

SynchronizationContextRepresents a target for work via its Post methodWindowsFormsSynchronizationContext

.Post() does Control.BeginInvoke

DispatcherSynchronizationContext.Post() does Dispatcher.BeginInvoke

AspNetSynchronizationContext.Post() ensures one-at-a-time

… // ~10 in .NET Framework, and you can write your own… // Is the core way for “await” to know how to put you back

Page 19: Async-await best practices in 10 minutes

SynchronizationContext and AwaitPrinciplesIn a server app, spinning up threads hurts scalabilty.The app (not the library) is in the best position to manage its own threads.Users will assume they know your method's implementation by looking at its signature.

GuidanceDefine an async signature “FooAsync” when your implementation is truly async.Define a sync signature "Foo" when your implementation is fast and won't deadlock.Don't use blocking calls to Wait() .Result in libraries; that invites deadlocks.

Page 20: Async-await best practices in 10 minutes

SynchronizationContext: ConfigureAwaitTask.ConfigureAwait(bool continueOnCapturedContext)await t.ConfigureAwait(true) // default

Post continuation back to the current context/scheduler

await t.ConfigureAwait(false)If possible, continue executing where awaited task completes

ImplicationsPerformance (avoids unnecessary thread marshaling)Deadlock (code shouldn’t block UI thread, but avoids deadlocks if it does)

Page 21: Async-await best practices in 10 minutes

Use ConfigureAwait(false)PrinciplesSynchronizationContext is captured before an await, and used to resume from await.In a library, this is an unnecessary perf hit.It can also lead to deadlocks if the user (incorrectly) calls Wait() on your returned Task..

GuidanceIn library methods, use "await t.ConfigureAwait(false);"

Page 22: Async-await best practices in 10 minutes

Await all the way

Page 23: Async-await best practices in 10 minutes

Library perf considerationsPrinciplesThe compiler provides, through the await keyword, sequential execution of the code.

GuidanceDon’t mix async-await with ContinuesWith.

Page 24: Async-await best practices in 10 minutes

Task.Run is the way to create new tasks

Page 25: Async-await best practices in 10 minutes

Task.RunPrinciplesTask.Run returns hot tasks (running or completed) created with settings suited to async-await.

GuidanceDon’t use Task.Factory.StartNew or the Task (or Task<T>) constructor.

Page 26: Async-await best practices in 10 minutes

Use the CancellationToken

Page 27: Async-await best practices in 10 minutes

Use the CancellationTokenPrinciplesThe CancellationToken structure is the way to signal and handle cancellation.

GuidanceIf you want your API to be cancellable, use cancellation tokens.If your code uses APIs that use cancellation tokens, use them.Always check the cancellation tokens.

Page 28: Async-await best practices in 10 minutes

Library perf considerations

Page 29: Async-await best practices in 10 minutes

Library perf considerationsPrinciplesAsync methods are faster than what you could write manually, but still slower than synchronous.The chief cost is in memory allocation (actually, in garbage collection).The "fast path" bypasses some allocations.

GuidanceAvoid designing "chatty" APIs where async methods are called in an inner loop; make them "chunky".If necessary, cache the returned Task object (even with cache size "1"), for zero allocations per call.As always, don't prematurely optimize!

Page 30: Async-await best practices in 10 minutes

Questões?

Page 31: Async-await best practices in 10 minutes

Resources• Talk: Async best practices

– http://blogs.msdn.com/b/lucian/archive/2013/11/23/talk-mvp-summit-async-best-practices.aspx

• Six Essential Tips For Async – Introduction– http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Three-Essential-Tips-

For-Async-Introduction

• Curah! async-await General– http://curah.microsoft.com/45553/asyncawait-general

• Curah! async-await and ASP.NET– http://curah.microsoft.com/44400/async-and-aspnet

Page 32: Async-await best practices in 10 minutes

Questões?

Page 33: Async-await best practices in 10 minutes

Patrocinadores “GOLD”

Twitter: @PTMicrosoft

http://www.microsoft.com/portugal

Twitter: @FindMoreC

http://www.findmore.eu

Page 35: Async-await best practices in 10 minutes

Patrocinadores “Bronze”

Page 36: Async-await best practices in 10 minutes

http://bit.ly/netponto-aval-50

* Para quem não puder preencher durante a reunião, iremos enviar um email com o link à tarde

Page 37: Async-await best practices in 10 minutes

Próximas reuniões presenciais22/11/2014 – Novembro – 50ª Reunião! (Lisboa)13/12/2014 – Dezembro (Lisboa)24/01/2015 – Janeiro (Lisboa)??/??/2015 – ????? (Porto)??/??/2015 – ????? (?????)

Reserva estes dias na agenda! :)