Presentation is loading. Please wait.

Presentation is loading. Please wait.

TechReady 16 4/1/2017 Async Clinic

Similar presentations


Presentation on theme: "TechReady 16 4/1/2017 Async Clinic"— Presentation transcript:

1 TechReady 16 4/1/2017 Async Clinic Lucian Wischik, Mads Torgersen, Stephen Toub (MSFT) Stephen Cleary (MVP) © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, 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.

2 Brainteasers

3 Symptom: Not Running Asynchronously
async void button1_Click(…) { … await Task.Run(() => work()); … } async void button1_Click(…) { … await ScheduleAsync(work); … } async Task ScheduleAsync(Action work) { work(); } Problem: Thinking ‘async’ forks. Solution: Use Task.Run around a synchronous method if you need to offload… but don’t expose public APIs like this.

4 Symptom: Completing Too Quickly
…; await Task.Delay(1000); …; …; Task.Delay(1000); …; Problem: Neglecting to await. Solution: Await your awaitables. Problem: Async void lambda. Solution: Use extreme caution (& knowledge) when passing around async lambdas as void-returning delegates. Parallel.For(0, 10, async i => { await Task.Delay(1000); }); Problem: Task<Task> instead of Task. Solution: Make sure you’re unwrapping your Tasks, explicitly (Unwrap) or implicitly. await Task.Run( async () => { await Task.Delay(1000); }); await Task.Factory.StartNew( async () => { await Task.Delay(1000); });

5 Symptom: Method Not Completing
async void button1_Click(…) { await FooAsync(); } async Task FooAsync() { await Task.Delay(1000); } async void button1_Click(…) { await FooAsync(); } async Task FooAsync() { await Task.Delay(1000).ConfigureAwait(false); } void button1_Click(…) { FooAsync().Wait(); } async Task FooAsync() { await Task.Delay(1000); } Problem: Deadlocking UI thread. Solution: Don’t synchronously wait on the UI thread. Problem: Deadlocking UI thread. Solution: Use ConfigureAwait(false) whenever possible. var tcs = new TaskCompletionSource<T>(); Task.Run(delegate { try { T result = Foo(); tcs.SetResult(result); } catch(Exception e) { tcs.SetException(e); } }); return tcs.Task; var tcs = new TaskCompletionSource<T>(); Task.Run(delegate { T result = Foo(); tcs.SetResult(result); }); return tcs.Task; Problem: Awaited task never completes. Solution: Always complete Tasks when the underlying operation has ended. Always.

6 Special Topics

7 TechReady 16 4/1/2017 Throttling (1) async Task LotsOfWorkAsync() { var throttle = Throttle<string>(async message => { await Task.Yield(); Console.WriteLine(message);}, maxParallelism: Environment.ProcessorCount); throttle.Post("lots"); throttle.Post("of"); throttle.Post("work"); throttle.Complete(); // Signal that we're done enqueuing work. await throttle.Completion; } static ITargetBlock<T> Throttle<T>(Func<T, Task> worker, int max) { var opts = new ExecutionDataflowBlockOptions() {MaxDegreeOfParallelism = max}; return new ActionBlock<T>(worker, opts); © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, 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.

8 TechReady 16 4/1/2017 Throttling (2) public async Task<List<House>> LoadHousesAsync(int first, int last) { var loadedHouses = new List<House>(); var queue = new Queue<int>(Enumerable.Range(first, last – first + 1)); // Throttle the rate of issuing requests... var worker1 = WorkerAsync(queue, loadedHouses); var worker2 = WorkerAsync(queue, loadedHouses); var worker3 = WorkerAsync(queue, loadedHouses); await Task.WhenAll(worker1, worker2, worker3); return loadedHouses; } * What would we do if there weren’t 5 houses but 500? * Can’t make 500 requests all at once. We need to throttle the rate of requests. * Here’s what I think is the easiest idiom. * A queue of work-items. * Async method WorkerAsync runs through the queue and fires requests, one after the other. * And if I kick off three of these workers, then I’ll have throttled it to 3 at a time! private async Task WorkerAsync(Queue<int> queue, List<House> results) { while (queue.Count > 0) int i = queue.Dequeue(); var house = await House.LoadFromDatabaseAsync(i); results.Add(house); } © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, 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.

9 Throttling (3) Explicitly Controlled SemaphoreSlim
await Task.WhenAll(from i in Enumerable.Range(0, N) select Task.Run(async delegate { … })); SemaphoreSlim var sem = new SemaphoreSlim(N); await sem.WaitAsync(); …; sem.Release(); ConcurrentExclusiveSchedulerPair var f = new TaskFactory( new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, N).ConcurrentScheduler); f.StartNew(…); // note: only counts tasks currently on a thread ActionBlock var ab = new ActionBlock<T>(async t => …, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = N });

10 Task-based Async Pattern (TAP)
“Async” suffix Signature Task<TResult> XxAsync( T1 Arg1, T2 Arg2, CancellationToken cancellationToken, IProgress<TProgress> progress); Parameters matching synchronous method (no ref or out) Cancellation/progress parameters only if supported Returns Task or Task<TResult> Behavior Returns quickly to caller Returned Task must be “hot” May complete synchronously Exceptions stored in returned Task (only usage exceptions allowed to escape synchronously)

11 async & await are about joins, not forks
public static Task PausePrintAsync() { // Requires a thread for all // of its processing return Task.Run(() => { Thread.Sleep(10000); Console.WriteLine("Hello"); }); } public static Task PausePrintAsync() { // Don’t consume threads // when no threads are needed var t = Task.Delay(10000); return t.ContinueWith(_ => { Console.WriteLine("Hello")); }); } Task Synchronous join Asynchronous join task.Wait(); await task;


Download ppt "TechReady 16 4/1/2017 Async Clinic"

Similar presentations


Ads by Google