Concurrency - responsiveness in .NET

Post on 01-Jul-2015

197 views 1 download

description

Concurrecy - responsiveness in .NET using async/await. These are the slides for NNUG meetup 2014-09-22 in Oslo.

Transcript of Concurrency - responsiveness in .NET

http://www.slideshare.net/martenrange/

Mårten RångeEricsson AB

@marten_range

ConcurrencyExamples for .NET

Responsive

PerformanceScalable algorithms

Three pillars of Concurrency

Scalability (CPU) Parallel.For

Responsiveness Task

async/await

Consistency lock

Interlocked.*

Mutex/Event/Semaphore

Monitor

Responsiveness

string ReadSomeText (string fileName){

using (var sr = new StreamReader(fileName)){

var result = sr.ReadToEnd ();return result;

}}

// Blocks the thread until IO completesvar text = ReadSomeText ("SomeText.txt");

Asyncronous programming allowsprograms to be responsive

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var first = await sr.ReadLineAsync();var second = await sr.ReadLineAsync();var third = await sr.ReadLineAsync();return first + second + third;

}}

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

// Is this code correct?var readTask = ReadSomeTextAsync ("SomeText.txt");var text = readTask.Result;

It depends

// Is this code correct (ignore exceptions)?async Task<string> ReadSomeTextAsync(string fileName){

++m_readingFiles;using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();--m_readingFiles;return result;

}}

It depends

// Does both TraceTheadId() trace the same id?async Task<string> ReadSomeTextAsync(string fileName){

TraceThreadId ();using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();TraceThreadId ();return result;

}}

It depends

What’s going on?

Your new ”best” friends

SynchronizationContext Console apps

Continues on ThreadPool thread

WindowsFormsSynchronizationContext Used by WindowsForms apps

Continues on the ”UI” thread

DispatcherSynchronizationContext Used by WPF and ASP.NET apps

Continues on the ”same” thread

SynchronizationContext

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

// Is this code correct?var readTask = ReadSomeTextAsync ("SomeText.txt");var text = readTask.Result;

Yes

// Is this code correct (ignore exceptions)?async Task<string> ReadSomeTextAsync(string fileName){

++m_readingFiles;using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();--m_readingFiles;return result;

}}

No

// Does both TraceTheadId() trace the same id?async Task<string> ReadSomeTextAsync(string fileName){

TraceThreadId ();using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();TraceThreadId ();return result;

}}

No

DispatcherSynchronizationContext&

WindowsFormsSynchronizationContext

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();return result;

}}

// Is this code correct?var readTask = ReadSomeTextAsync ("SomeText.txt");var text = readTask.Result;

No

// Is this code correct (ignore exceptions)?async Task<string> ReadSomeTextAsync(string fileName){

++m_readingFiles;using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();--m_readingFiles;return result;

}}

Yes

// Does both TraceTheadId() trace the same id?async Task<string> ReadSomeTextAsync(string fileName){

TraceThreadId ();using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync();TraceThreadId ();return result;

}}

Yes

So…

Is ”invisible”

Is a thread-global state

Impacts the behavior of your code significantly

As an application developer you can make assumptions

As a library developer you can’t make assumptions

SynchronizationContext

ConfigureAwait

async Task<string> ReadSomeTextAsync(string fileName){

using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync().ConfigureAwait (false);

return result;}

}

// Is this code correct?var readTask = ReadSomeTextAsync ("SomeText.txt");var text = readTask.Result;

Yes

// Is this code correct (ignore exceptions)?async Task<string> ReadSomeTextAsync(string fileName){

++m_readingFiles;using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync().ConfigureAwait (false);

--m_readingFiles;return result;

}}

No

// Does both TraceTheadId() trace the same id?async Task<string> ReadSomeTextAsync(string fileName){

TraceThreadId ();using (var sr = new StreamReader(fileName)){

var result = await sr.ReadToEndAsync().ConfigureAwait (false);

TraceThreadId ();return result;

}}

No

async/await tries to be what we want

async/await reminds me of…

What we need

Do one thing Responsiveness

Predictable semantics Continuation is executed by a thread-pool thread

Visibility Thread-switching should be visible in code

F# async

// Focuses on responsivenesslet gameLoop =

async {// Switching to new thread is explicitdo! Async.SwitchToNewThread ()while true do

// let! is like await in C#let! messages = fromVisual.AsyncDequeue 1000

for message in messages doprocessMessage message

}

C#

yield Special support for enumerators

LINQ Special support for SQL-like syntax

async/await Special support for asynchronous programming

F#

seq { for x in 0..10 -> i } Enumerators implemented using Computation Expressions

query { for c in db.Customers do select c } SQL-like syntax implemented using Computation Expressions

async { let! r=fromVisual.AsyncDequeue 1000 in r } Asynchronous programming using Computation Expressions

Computation Expressions

With async/await always consider the…

SynchronizationContext

SynchronizationContext

SynchronizationContextSynchronizationContext

SynchronizationContextSynchronizationContextSynchronizationContextSynchronizationContext

SynchronizationContextSynchronizationContext

SynchronizationContext

Mårten RångeEricsson AB

@marten_range

Links

Presentation http://www.slideshare.net/martenrange/

Code https://github.com/mrange/presentations/

DIY asynchronous workflows in F# http://mrange.wordpress.com/2014/06/12/diy-asynchronous-workflows-in-f/

Asynchronous programming with async/await http://msdn.microsoft.com/en-us/library/hh191443.aspx