+ All Categories
Home > Documents > Async’ing Your Way to a Successful App with .NET

Async’ing Your Way to a Successful App with .NET

Date post: 15-Feb-2016
Category:
Upload: hina
View: 39 times
Download: 0 times
Share this document with a friend
Description:
Async’ing Your Way to a Successful App with .NET. Stephen Toub Visual Studio 3-301. Agenda. 6 Tips for Building Better Apps. #1. Wrap Events with Tasks to Improve Control Flow. public async Task RunStoryboardAsync ( this Storyboard sb ) { - PowerPoint PPT Presentation
24
Transcript
Page 1: Async’ing  Your Way to a  Successful App with .NET
Page 2: Async’ing  Your Way to a  Successful App with .NET

Async’ing Your Way to a Successful App with .NET

Stephen ToubVisual Studio3-301

Page 3: Async’ing  Your Way to a  Successful App with .NET

6 Tips for Building Better AppsAgenda

Page 4: Async’ing  Your Way to a  Successful App with .NET

Library SupportTaskCompletionSource<T>

Can be used to wrap arbitrary operations as a TaskOnce operations are exposed as Tasks, you can compose over them as you

would any Task

Patternpublic async Task RunStoryboardAsync(this Storyboard sb){ var tcs = new TaskCompletionSource<bool>();

EventHandler<object> handler = (s,e) => tcs.SetResult(true); sb.Completed += handler; sb.Begin();

await tcs.Task; sb.Completed -= handler;}

public Task<T> RunAsync(Func<T> func){ var tcs = new TaskCompletionSource<T>();

ThreadPool.QueueUserWorkItem(delegate { try { tcs.SetResult(func()); } catch (Exception e) { tcs.SetException(e); } }); return tcs.Task;}

public Task Delay(int milliseconds){ var tcs = new TaskCompletionSource<bool>();

new Timer(_ => tcs.SetResult(true)).Change(milliseconds, -1);

return tcs.Task;}

public async Task WaitForClickAsync(this Button button){ var tcs = new TaskCompletionSource<bool>();

RoutedEventHandler handler = (s,e) => tcs.SetResult(true); button.Click += handler;

await tcs.Task; button.Click -= handler;}

Wrap Events with Tasks to Improve Control Flow

#1

public Task<T> FooAsync(){ var tcs = new TaskCompletionSource<T>();

// schedule something asynchronously // to invoke tcs.Set*

return tcs.Task;}

Page 5: Async’ing  Your Way to a  Successful App with .NET

Awaiting tasks makes it easy to compose sequences or graphs of operations.

Wrapping Events with Tasks to Improve Control Flow

Page 6: Async’ing  Your Way to a  Successful App with .NET

Use Cancellation to Improve ResponsivenessLibrary SupportCancellationToken as a composable cancellation mechanism var cts = new CancellationTokenSource(); SomeMethod(cts.Token); cts.Cancel();

Pattern

#2

public async Task FooAsync(){ … await SomeDotNetAsync(); await SomeWinRTAsync(); …}

public async Task FooAsync(CancellationToken cancellationToken){ … await SomeDotNetAsync(cancellationToken); await SomeWinRTAsync().AsTask(cancellationToken); …}

Page 7: Async’ing  Your Way to a  Successful App with .NET

Responsiveness isn’t just about keeping the UI available for interaction. More broadly, it’s about doing what the user wants when the user wants.

Using Cancellation to Improve Responsiveness

Page 8: Async’ing  Your Way to a  Successful App with .NET

Be Wary of “Async Void”Language Supportasync void, async Task, & async Task<T>

async Task & async Task<T> return handles to the outstanding workasync void is a “fire-and-forget” mechanism

GuidanceUse async void methods only for top-level entry points (e.g. UI event handlers)

(Use and await async Task-returning methods everywhere else)

Avoid passing async lambdas to void-returning delegates(Don’t pass async lambdas to WinRT methods unless you really know what you’re

doing)

#3

Page 9: Async’ing  Your Way to a  Successful App with .NET

Many problems in async code can be traced back to using “async void” incorrectly.

Avoiding “async void”

Page 10: Async’ing  Your Way to a  Successful App with .NET

Use ConfigureAwait for Perf & ResponsivenessSynchronizationContext represents a target for workDispatcherSynchronizationContext (Post: Dispatcher.BeginInvoke)WinRTSynchronizationContext (Post: CoreDispatcher.RunAsync)

Await Behavior

GuidanceUse ConfigureAwait(false) on all awaits in all methods with code that’s context agnostic (which is most libraries)

#4

await task; // force continuation back to the current sync contextawait task.ConfigureAwait(false); // try to continue executing where awaited task completes

Page 11: Async’ing  Your Way to a  Successful App with .NET

Using ConfigureAwait

Use ConfigureAwait(false)

async void button1_Click(…){ await DoWorkAsync();}

async void button1_Click(…){ DoWorkAsync().Wait();}

async Task DoWorkAsync(){ await Task.Run(…); Console.WriteLine("Done task");}

1. DoWorkAsync invoked on UI thread

3. Await captures SynchronizationContext

and hooks up a continuation to run when

task completes

4. UI blocks waiting for DoWorkAsync-returned Task to

complete6. UI thread still blocked waiting for async operation to

complete.Deadlock! .ConfigureAwait(false) avoids

deadlock.

async Task DoWorkAsync(){ await Task.Run(…).ConfigureAwait(false); Console.WriteLine("Done task");}

2. Task.Run schedules work to run on thread

pool

5. Task.Run task completes on pool & invokes continuation which Posts back

to UI thread

Page 12: Async’ing  Your Way to a  Successful App with .NET

Avoiding using the UI thread unless you actually need to.

Using ConfigureAwait for Responsiveness & Perf

Page 13: Async’ing  Your Way to a  Successful App with .NET

Avoid “Sync over Async”, “Async over Sync” in Libraries

#5

Page 14: Async’ing  Your Way to a  Successful App with .NET

What does asynchrony really mean?SynchronousPerform something here and now.I’ll regain control to execute something else when it’s done.

AsynchronousInitiate something here and now.I’ll regain control to execute something else “immediately”.

Page 15: Async’ing  Your Way to a  Successful App with .NET

public static void PausePrintAsync() { ThreadPool.QueueUserWorkItem(_ => PausePrint());}

public static Task PausePrintAsync() { return Task.Run(() => PausePrint());}

public static Task PausePrintAsync() { var tcs = new TaskCompletionSource<bool>(); new Timer(_ => { Console.WriteLine("Hello"); tcs.SetResult(true); }).Change(10000, Timeout.Infinite); return tcs.Task;}

public static async Task PausePrintAsync() { await Task.Delay(10000); Console.WriteLine("Hello");}

Sync vs Async“Pause for 10 seconds, then output 'Hello' to the console.”Synchronous Asynchronous

public static void PausePrint() { var end = DateTime.Now + TimeSpan.FromSeconds(10); while(DateTime.Now < end); Console.WriteLine("Hello");}

public static void PausePrint() { Task t = PausePrintAsync(); t.Wait();}

“async

over sync”

“syncover

async”

Possible responsiveness problems

Possible scalability problems

Page 16: Async’ing  Your Way to a  Successful App with .NET

Avoid “Sync over Async”, “Async over Sync” in LibrariesGuidanceBe honest! Suffix should help caller to understand implementation.Define “FooAsync” iff you’re not thread-bound (with a few notable exceptions).

Don’t just expose FooAsync as “return Task.Run(() => Foo());”Define “Foo” iff you have a faster sync implementation that won’t deadlock.

Don’t just expose Foo as “FooAsync().Wait();”

ExceptionsMethods exposed from .WinMD assembliesOverrides in some class hierarchies

#5

Page 17: Async’ing  Your Way to a  Successful App with .NET

Use Visual Studio’s async toolingVisual Studio 2012: Stepping with AsyncStep InStep OverStep Out

#6

Page 18: Async’ing  Your Way to a  Successful App with .NET

Stepping through your code as if it were synchronous.

Stepping in, over, and out with async

Page 19: Async’ing  Your Way to a  Successful App with .NET

Debugging Async in Visual Studio 2013Visual Studio 2013: Call Stack WindowProvides a “call stack” across async points.

Visual Studio 2013: Tasks WindowSee and navigate from a list all active async operations.

#7

Page 20: Async’ing  Your Way to a  Successful App with .NET

Knowing how you got here and what’s going on

Using the Call Stack and Task Windows with async

Page 21: Async’ing  Your Way to a  Successful App with .NET

Summary

6 Tips for Building Better Apps1. Wrap events with tasks to improve control flow2. Use cancellation to improve responsiveness3. Be wary of “async void”4. Use ConfigureAwait to improve perf &

responsiveness5. Avoid exposing “sync over async” or “async over

sync”6. Use Visual Studio’s async tooling

Questions? Comments?

Page 22: Async’ing  Your Way to a  Successful App with .NET

ResourcesParallel Programming in .NET Blog:http://blogs.msdn.com/pfxteam

Task-based Async Pattern Whitepaperhttp://aka.ms/tap

Page 23: Async’ing  Your Way to a  Successful App with .NET

Evaluate this session

Scan this QR code to evaluate this session and be automatically entered in a drawing to win a prize!

Page 24: Async’ing  Your Way to a  Successful App with .NET

© 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.


Recommended