iasyncresult ar = beginsomething(…); // do other work, checking ar.iscompleted int result =...

51

Upload: laura-cross

Post on 13-Dec-2015

219 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);
Page 2: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

How to Build ASP.NET Web Applications Using AsyncRowan Miller

DEV-B337

Page 3: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

AgendaA brief history of async in .NETAsync scenarios with demosTips, tricks & no-nos

Page 4: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET

Page 5: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET.NET Framework 1.0

No asynchronous programming model

Page 6: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET.NET Framework 1.1

Asynchronous programing model (APM)Call BeginXyz which returns IAsyncResultWatch IAsyncResult until completedCall EndXyz to get the actual result

IAsyncResult ar = BeginSomething(…);// Do other work, checking ar.IsCompletedint result = EndSomething(ar);

Page 7: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET.NET Framework 2.0

Event-based asynchronous pattern (EAP)Subscribe to XyzCompletedCall XyzAsync to start work

SomethingCompleted += (sender, e) =>{ // Do something with result};SomethingAsync(…);

Page 8: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET.NET Framework 4.0

Task Paralell Library (TPL)Call XyzAsync which return Task<TResult>Watch Task until completedGet result directly from Task

Task<int> task = SomethingAsync(…);// Do other work, checking task.Statusint result = task.Result;

Page 9: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

A brief history of async in .NET.NET Framework 4.5

async/await keywordsYour code structured the same as synchronous codeCompiler creates async code using TPL

int result = await SomethingAsync(…);

Page 10: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Async scenarios

Page 11: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Asynchronous != parallel

SequentialOrdered set of stepsCode executes when previous operation is done

ParallelMultiple operations executing at onceOperations start/complete at different times

SynchronousThread is blocked until execution completes

AsynchronousThread only blocked when there is work to do

Page 12: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Async scenariosI/O operations (database, file, network, etc.)ParallelismLong-running event-driven (streaming, long polling, etc.)

Page 13: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

I/O operations

Page 14: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Traditional web request handling

BusyBusy Busy Busy

Request Queue

Thread Pool

Page 15: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Synchronous Codepublic int SumPageSizes(IList<Uri> uris) {    int total = 0;

    foreach (var uri in uris) {        var data = new WebClient().DownloadData(uri);        total += data.Length;    }

    return total;}

Page 16: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Asynchronous web request handling

Request Queue

Thread Pool

Page 17: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Synchronous Codepublic int SumPageSizes(IList<Uri> uris) {    int total = 0;

    foreach (var uri in uris) {        var data = new WebClient().DownloadData(uri);        total += data.Length;    }

    return total;}

Page 18: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Asynchronous code without async/awaitpublic void SumPageSizesAsync(IList<Uri> uris, Action<int, Exception> callback) {    SumPageSizesAsyncHelper(uris.GetEnumerator(), 0, callback);}

private void SumPageSizesAsyncHelper(IEnumerator<Uri> enumerator, int total, Action<int, Exception> callback) {    try {        if (enumerator.MoveNext()) {            var client = new WebClient();            client.DownloadDataCompleted += (sender, e) => {                if (e.Error != null) { enumerator.Dispose(); callback(0, e.Error); }                else SumPageSizesAsyncHelper(enumerator, total + e.Result.Length, callback);            };            client.DownloadDataAsync(enumerator.Current);        }        else  {            enumerator.Dispose();            callback(total, null);        }    }    catch (Exception ex)  { enumerator.Dispose();        callback(0, ex);    }}

Page 19: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Synchronous Codepublic int SumPageSizes(IList<Uri> uris) {    int total = 0;

    foreach (var uri in uris) {        var data = new WebClient().DownloadData(uri);        total += data.Length;    }

    return total;}

Page 20: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Asynchronous code using async/awaitpublic async Task<int> SumPageSizesAsync(IList<Uri> uris) {    int total = 0;

    foreach (var uri in uris) {       var data = await new WebClient().DownloadDataTasksync(uri);        total += data.Length;    }

    return total;}

Page 21: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Async in ASP.Net WebForms

Page 22: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

WebForms takeawaysAwait frees up thread until operation is finishedUsing async does not affect clientSet Async page attribute to use new async pipelineAlways use RegisterAsyncTask to call async codeASP.NET takes care of thread affinity

Page 23: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Async in ASP.NET WebAPI/MVC

Page 24: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

MVC/WebAPI takeawaysAsync is simple - just mark the action as asyncAsync is transparent to callers of WebAPIEntity Framework 6 enables async database calls

Page 25: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

I/O operationsError conditions

Page 26: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Cancellation tokensAllow caller to terminate an in-flight async taskASP.NET has three built-in tokensRequestTimeout, ClientDisconnected, & AsyncTimeout

Page 27: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Cancellation tokens

Page 28: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Cancellation tokens takeawaysCancellation tokens further reduce thread usageASP.NET has built in cancellation tokensUse CancellationTokenSource to combine tokens

Page 29: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Parallelism

Page 30: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);
Page 31: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Two types of parallelismMultiple asynchronous operationsTwo or more awaitable operationsNo additional threads used

Multiple synchronous operationsTask.Run, ThreadPool.QueueUserWorkItem, etc.Each operation uses a threadSame thread pool as ASP.NET

Page 32: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Parallelism

Page 33: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Parallelism takeawaysParallelism can reduce request timeBe careful with synchronous parallelismThreads come from same pool used to serve requests

Page 34: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Async in an HttpHandler

Page 35: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Tips, tricks & no-nos

Page 36: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Avoid work on “background threads”There are no background threads on serversAll threads come form the same pool used to serve requestsMoving to another thread just adds cost

Use Task.FromResult if result needs to look async TaskCompletionSource<T> if you need to return non-result (faulted, cancelled, etc.)

Page 37: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Using ASP.NET intrinsics on worker threadsHttpContext.Current, Request, Response, etc.Not setup to use on worker threads you start

Async/await will take care of this for youProvided you start using them on the request thread

Alternative is to use SynchronizationContext.Post

Page 38: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Avoid using Task.WaitCalling Wait blocks the current threadTask.Result on an uncompleted task also blocksCan easily cause deadlocks in ASP.NETUse await or Task.WhenAll instead

Page 39: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Demo

Deadlocks from using Task.Wait

Page 40: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Avoid Task.ContinueWithContinueWith is not aware of SynchronizationContextAlways puts you on a new threadUse async/await instead

Page 41: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Be careful with parallelismMultiple requests * multiple threads = a lot of threadsAll threads come form the same pool used to serve requestsThreads consume min ¼Mb memory each

Kicking off multiple awaitable async tasks is fine

Page 42: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Don’t use thread local storageYou may swap physical threadsDon’t use [ThreadStatic]Use HttpContext.ItemsIf your using async/await ASP.NET will take care of thread hops

Don’t assume this doesn’t apply to your sync codeOther async components in the pipeline can cause thread hops

Page 43: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Don’t call fire & forget methodsYour code could be terminated at any timeUse WebBackgrounderhttp://nuget.org/packages/WebBackgrounder/

Write a worker process for more complex tasks

Page 44: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Use HttpTaskAsyncHandlerIHttpAsyncHandler is a complicated interfaceHttpTaskAsyncHandler takes care of a lot for you

Page 45: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

ResourcesParallel Programming with .NET Bloghttp://blogs.msdn.com/pfxteam/

Asynchrony in .NET Whitepaperhttp://msdn.com/library/vstudio/hh191443.aspx

ASP.NET Async Tutorialhttp://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45

Page 46: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Plan details and subscriber benefits

Included for certain paid MSDN subscribers:

Free Plan for up to 5 users

Additional information at http://tfs.visualstudio.com

* Capability in preview – limits may apply. Authoring load tests requires Visual Studio Ultimate 2013 Preview.

Version control (TFVC or Git) Comment on changesets & commits Work item tracking and tagging Team rooms Agile planning tools Feedback Management Agile Portfolio Management* Build* Web-based test case management* Load testing*

New!

New!

New!

New!

Page 47: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

MSDN Subscribers –

Accelerate Your Development & Test using Cloud VMsWe’ve enhanced the Windows Azure MSDN benefit and added cloud use rights for select MSDN software. You’ve already got it, now use it! 

Activate and try out your Windows Azure MSDN benefit today & you could win an Aston Martin V8 Vantage!

Learn more and activate today at http://aka.ms/AzureContest

Page 48: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

msdn

Resources for Developers

http://microsoft.com/msdn

Learning

Microsoft Certification & Training Resources

www.microsoft.com/learning

TechNet

Resources

Sessions on Demand

http://channel9.msdn.com/Events/TechEd

Resources for IT Professionals

http://microsoft.com/technet

Page 49: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Complete an evaluation on CommNet and enter to win!

Page 50: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

Evaluate this session

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

Page 51: IAsyncResult ar = BeginSomething(…); // Do other work, checking ar.IsCompleted int result = EndSomething(ar);

© 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.