3. Wikipedia
“Asynchronous events are those occurring independently
of the main program flow. Asynchronous actions are
actions executed in a non-blocking scheme, allowing the
main program flow to continue processing”
4. You Should Use Async Today
• Your UI always remains responsive
• No need to guard against race conditions
• No ugly callbacks
• Compiler does all the heavy li!ing
5.
6. Async in C#
• New major feature of C# 5.0
Makes asynchronous programming a first-class citizen in C#
Important part of C# – as significant as LINQ
• New async modifier keyword introduced
• Methods, lambda expressions, and anonymous methods can be
asynchronous
• New contextual keyword await introduced
7. Adding Async to Your Codebase
• Decorated with new async modifier
• Async method must return one of
Task, Task<T> or void type
• Async anonymous method and lambdas
Delegates returning Task, Task<T> or void
• Very few restrictions
No ref or out parameters allowed
No unsafe code
No Main async method
No async iterators (aka IAsyncEnumerable<T>)
8. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Example: Calculating a Price Asynchronously
public
async
Task<int>
CalculatePriceAsync
(Item[]
items)
{
int
price;
//
Calculate
price
asynchronously
and
return
the
value
return
price;
}
public
override
void
ViewDidLoad
()
{
button.TouchDown
+=
async
(sender,
e)
=>
{
//
This
is
asynchronous
handler
};
}
9. Await Introduction
• Await can be used in async context only
Marks a suspension point
Can be used anywhere (except catch and finally blocks)
Requires awaitable types (Task, Task<T> but can be any
custom type)
As many as you like inside async block
11. Cancelling an Async Task
• CancellationToken controls cancellation process
• Async method needs explicitly support it
Usually another method overload
Task SaveAsync (CancellationToken token)
• Caller calls Cancel on CancellationTokenSource
Async method stops and returns Task with cancelled state
Implementation detail how quickly async method terminates
13. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Async Language Features
public
async
Task
RealAsync
()
{
//
This
is
real
async
heavy
code
(only
7
awaits
someone
else
will
//
certainly
do
better)
var
test
=
new
TestClass
(await
CallAsync
()
|
await
CallAsync
())
{
Latitude
=
await
GetLatitudeAsync
(await
AnotherAsync
()),
Roles
=
from
role
in
await
GetRolesAsync
()
where
role
==
"agent"
select
role
};
....
test
[await
CallAsync
()]
=
new
int[]
{
33,
await
GetIntAsync
()
};
...
}
14. Best Practices
• Use Async naming suffix for asynchronous methods
LoadAsync, SendAsync, etc.
Only recommended naming convention
• Return Task or Task<T> preferably
Task for SaveAsync like methods
Task<T> for ReadAsync like methods
Leave async void to event handlers only
• Support cancellation, if possible
15. Synchronization Context
• Framework abstraction over UI toolkit threading model
NSRunLoop, DispatchContext in Xamarin.iOS
MainLooper in Xamarin.Android
Dispatcher in WPF
etc.
• Await uses synchronization context to restore back suspended
context
SynchronizationContext::Post method is used
Suspension on UI thread resumes back on same UI thread as
“expected”
16. Sometimes Things Go Wrong
• Async returning Task or Task<T>
Task state is set to Faulted
Exception is re-thrown when Task is checked (awaited)
• Async void
Fire and forget asynchrony
Exception is thrown on current synchronization context and your
app will crash
18. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Exception Throwing
public
async
Task<int>
CalculatePriceAsync
(Item[]
items)
{
if
(items
==
null)
{
//
Throw
before
suspension
throw
new
ArgumentNullException
("items");
}
...
var
price
=
await
CalculatePriceAsync
(items);
if
(price
<
0)
{
//
Throw
after
suspension
throw
new
ArgumentException
("Invalid
items");
}
...
}
19. Diving Deeper
• Await can work with any type which implements the awaiter
pattern
• Task and Task<T> types do since .NET 4.5
• Any custom type can be made awaitable
Has an accessible method called GetAwaiter returning a type which
Implements the interface INotifyCompletion
Has property IsCompleted of type bool
Has method GetResult with no parameters
20. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Custom await Behaviour
public
async
Task<int>
SomeAsync
()
{
...
await
3000;
//
This
does
not
compile
unless
we
provide
custom
awaiter
...
}
//
Name
of
the
method
is
important
static
TaskAwaiter
GetAwaiter
(this
int
millisecondsDelay)
{
return
Task.Delay
(millisecondsDelay).GetAwaiter
();
}
21. Async Deadlocks
• await restores execution context based on current
SynchronizationContext
Good for most application code
Bad for most library code
• Don’t block the UI thread
Good old rule still applies in async world
Use await when possible
22. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Async Deadlock Example
public
async
Task<int>
CalculatePriceAsync
(Item[]
items)
{
using
(var
cmd
=
CreateSqlCommand
(Calculations.TotalPrice,
items))
{
using
(var
r
=
await
cmd.ExecuteReaderAsync
())
{
.....
}
}
}
//
The
method
itself
cannot
be
async
public
override
bool
FinishedLaunching
(UIApplication
app,
NSDictionary
options)
{
....
int
price
=
CalculatePriceAsync
(items).Result;
//
Synchronous
wait
//
This
line
won’t
be
reached
if
flow
suspension
occurred
}
23. Controlling the Synchronization Context
• ConfigureAwait (bool)
Controls captured context behaviour
• true value - default behaviour
Continue execution on context async was called from
Important for UI to switch back to UI context
• false value
Avoids expensive context switching
Avoids possible deadlocks on blocking UI
24. 01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Async Deadlock Fixed
public
async
Task<int>
CalculatePriceAsync
(Item[]
items)
{
using
(var
cmd
=
CreateSqlCommand
(Calculations.TotalPrice,
items))
{
using
(var
r
=
await
cmd.ExecuteReaderAsync
().ConfigureAwait
(false))
{
//
The
context
is
not
restored
but
that’s
fine
for
no
UI
method
}
}
}
//
The
method
itself
cannot
be
async
public
override
bool
FinishedLaunching
(UIApplication
app,
NSDictionary
options)
{
....
int
price
=
CalculatePriceAsync
(items).Result;
//
Synchronous
wait
//
Program
continues
when
the
wait
is
signalled
}
25. Combinators
• Asynchronously wait on multiple asynchronous operations
Better than individual awaits of multiple tasks
The result can be awaited (Task of Tasks)
• Task.WhenAll (IEnumerable<Task>)
Completes when all of the individual tasks have completed
• Task.WhenAny (IEnumerable<Task>)
Completes when any of the individual tasks have completed
26. The Compiler Magic
• Compiler does all the “magic”
• Local variable and parameters are li!ed into compiler generated
type
Compiler converts variables and parameters to fields
• Any stack values need to be li!ed too
Stack needs to be restored a"er suspension
• Try-Catch block over any async block
• No suspension when awaited task finished
27. Best Practices - Performance
• Use ConfigureAwait when you can
• Reduce number of local variables
Move async block into separate method or lambda expression
Pass variables as parameters
Avoid deep await usage
• Cache Task not task result
• Don’t over use async
Use async only when appropriate (unreliable tasks, running >50ms)
Async has its own overhead
28. Get Your Hands on Async
• Async is available today
Xamarin.iOS Beta release
Xamarin.Android Beta release
Xamarin Studio async support
• Give us feedback on our new async API
Forums
Bugzilla
Mailing list
IRC