1 / 11

Async Clinic

Async Clinic. Lucian Wischik, Mads Torgersen, Stephen Toub (MSFT) Stephen Cleary (MVP). Brainteasers. Symptom: Not Running A synchronously. async void button1_Click(…) { … await Task .Run (() => work()); … }.

claus
Télécharger la présentation

Async Clinic

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Async Clinic Lucian Wischik, Mads Torgersen, Stephen Toub (MSFT)Stephen Cleary (MVP)

  2. Brainteasers

  3. Symptom: Not Running Asynchronously async voidbutton1_Click(…) { …awaitTask.Run(() => work()); …} async voidbutton1_Click(…){ …await ScheduleAsync(work); …}asyncTaskScheduleAsync(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 …;Task.Delay(1000);…; Problem: Neglecting to await. Solution: Await your awaitables. …;awaitTask.Delay(1000);…; Problem: Async void lambda. Solution: Use extreme caution (& knowledge) when passing around async lambdas as void-returning delegates. Parallel.For(0, 10, asynci => { awaitTask.Delay(1000);}); Problem: Task<Task> instead of Task. Solution: Make sure you’re unwrapping your Tasks, explicitly (Unwrap) or implicitly. awaitTask.Run(async() => { awaitTask.Delay(1000); }); awaitTask.Factory.StartNew( async() => { awaitTask.Delay(1000); });

  5. Symptom: Method Not Completing asyncvoidbutton1_Click(…) {awaitFooAsync();}asyncTaskFooAsync() { awaitTask.Delay(1000).ConfigureAwait(false); } voidbutton1_Click(…) {FooAsync().Wait();}asyncTaskFooAsync() { awaitTask.Delay(1000); } asyncvoidbutton1_Click(…) {awaitFooAsync();}asyncTaskFooAsync() { awaitTask.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. vartcs = newTaskCompletionSource<T>();Task.Run(delegate { T result = Foo();tcs.SetResult(result);});returntcs.Task; vartcs = newTaskCompletionSource<T>();Task.Run(delegate {try { T result = Foo();tcs.SetResult(result); }catch(Exception e) { tcs.SetException(e); }});returntcs.Task; Problem: Awaited task never completes. Solution: Always complete Tasks when the underlying operation has ended. Always.

  6. Special Topics

  7. Throttling (1) asyncTaskLotsOfWorkAsync(){varthrottle = Throttle<string>(asyncmessage =>{awaitTask.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. awaitthrottle.Completion; } staticITargetBlock<T> Throttle<T>(Func<T, Task> worker, intmax){ varopts = newExecutionDataflowBlockOptions() {MaxDegreeOfParallelism = max}; returnnewActionBlock<T>(worker,opts); }

  8. Throttling (2) publicasyncTask<List<House>> LoadHousesAsync(int first, int last) { varloadedHouses = newList<House>(); var queue = newQueue<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); awaitTask.WhenAll(worker1, worker2, worker3); returnloadedHouses; } privateasyncTaskWorkerAsync(Queue<int> queue, List<House> results) { while (queue.Count > 0) { inti = queue.Dequeue(); var house = awaitHouse.LoadFromDatabaseAsync(i); results.Add(house); } }

  9. Throttling (3) Explicitly Controlled await Task.WhenAll(fromiinEnumerable.Range(0, N) selectTask.Run(asyncdelegate { … })); SemaphoreSlim varsem = newSemaphoreSlim(N); awaitsem.WaitAsync(); …; sem.Release(); ConcurrentExclusiveSchedulerPair var f = newTaskFactory( newConcurrentExclusiveSchedulerPair(TaskScheduler.Default, N).ConcurrentScheduler); f.StartNew(…); // note: only counts tasks currently on a thread ActionBlock varab = newActionBlock<T>(async t => …, newExecutionDataflowBlockOptions { MaxDegreeOfParallelism = N });

  10. Task-based Async Pattern (TAP) Signature Task<TResult> XxAsync( T1 Arg1, T2 Arg2, CancellationTokencancellationToken, IProgress<TProgress> progress); “Async” suffix 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 publicstatic Task PausePrintAsync() { // Don’t consume threads // when no threads are needed vart = Task.Delay(10000); returnt.ContinueWith(_ => { Console.WriteLine("Hello")); }); } publicstatic Task PausePrintAsync() { // Requires a thread for all // of its processing returnTask.Run(() => { Thread.Sleep(10000); Console.WriteLine("Hello"); }); } Task Synchronous join Asynchronous join task.Wait(); awaittask;

More Related