Asynchronous programming Deadlock All The Things! Filip Ekberg [email protected] http://fekberg.com +61 (401) 157-608 @fekberg C# Smorgasbord Page 2 / Copyright ©2014 by Readify Pty Ltd.

Download Report

Transcript Asynchronous programming Deadlock All The Things! Filip Ekberg [email protected] http://fekberg.com +61 (401) 157-608 @fekberg C# Smorgasbord Page 2 / Copyright ©2014 by Readify Pty Ltd.

Asynchronous
programming
Deadlock All The Things!
Filip Ekberg
[email protected]
http://fekberg.com
+61 (401) 157-608
@fekberg
C# Smorgasbord
Page 2 / Copyright ©2014 by Readify Pty Ltd
Asynchronous programming?
› Processing allowed before current execution is done,
such as read/write to disk
› So is this the same as parallel? Not quite.
Page 3 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Async + Parallel
12:38
Process
records
Asynchronous task
Sort
data
Load app
content
Page 4 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Async? Never heard of it.
› Ajax - Asynchronous JavaScript and XML
› Request data
› Handle the response when available
Page 5 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Introducing Async and Await
› Two new Contextual Keywords as of .NET 4.5
› Meaning it does all the hard work for you
public async Task RunAsync()
{
await Task.Run(() => { });
}
Page 6 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Marking a method as Async
› This will indicate that the method will be executed from
within a state machine
› Adds overhead
› If it is not actually awaiting something, don’t mark it
as async!
› Simply marking as async doesn’t make it async!
Page 7 / Copyright ©2014 by Readify Pty Ltd
@fekberg
What do you think happens?
private void Button_Click()
{
try
{
Run();
}
catch (Exception ex)
{
}
}
public void Run()
{
throw new Exception();
}
Page 8 / Copyright ©2014 by Readify Pty Ltd
@fekberg
What do you think happens?
private void Button_Click()
{
try
{
RunAsync();
}
catch (Exception ex)
{
}
}
public async void RunAsync()
{
throw new Exception();
}
Page 9 / Copyright ©2014 by Readify Pty Ltd
@fekberg
The second one crashes!
› Async void is EVIL!
› Marking a method as async wraps it inside a state
machine
[AsyncStateMachine(typeof(<RunAsync2>d__0)), DebuggerStepThrough]
public void RunAsync2()
{
<RunAsync2>d__0 d__;
d__.<>4__this = this;
d__.<>t__builder = AsyncVoidMethodBuilder.Create();
d__.<>1__state = -1;
d__.<>t__builder.Start<<RunAsync2>d__0>(ref d__);
}
Page 10 / Copyright ©2014 by Readify Pty Ltd
@fekberg
How do we handle this?
› Use Task as a return type instead
› Always await your async calls
private void Button_Click()
{
RunAsync();
}
public async Task RunAsync()
{
throw new Exception();
}
Silently fails
private async void Button_Click()
{
try
{
await RunAsync();
}
catch (Exception ex)
{
}
}
“Validates” and lets you catch
any possible exceptions
Page 11 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Proper Async method
public async Task BoilEggsAsync(int amountOfEggs)
{
await BoilAsync(amountOfEggs);
}
public Task BoilEggsAsync(int amountOfEggs)
{
<BoilEggsAsync>d__5 d__;
d__.<>4__this = this;
d__.amountOfEggs = amountOfEggs;
d__.<>t__builder = AsyncTaskMethodBuilder.Create();
d__.<>1__state = -1;
d__.<>t__builder.Start<<BoilEggsAsync>d__5>(ref d__);
return d__.<>t__builder.Task;
}
Page 12 / Copyright ©2014 by Readify Pty Ltd
Awaiting a result
› Awaiting a task will schedule a continuation block
› Everything after the awaiting task will be executed
when the task is done executing
public async Task RunAsync()
{
var resultTask = Task<string>.Run(() => {
Thread.Sleep(2000);
return "Hello World!";
});
Back on the UI thread after
the waiting is done
var result = await resultTask;
}
Page 13 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Example of deadlocking
› Wait() for an asynchronous task on the UI thread,
making it impossible for the state machine to signal
that it is completed!
public async Task RunAsync()…
RunAsync().Wait();
Page 14 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Things to consider
› Don’t mark void methods as asynchronous, you will have no way of
tracking it
› Tasks swallow Exceptions!
› Don’t explicitly .Wait() this is an easy path to deadlocking
› Follow the naming convention MyMethodAsync
› Don’t lie by wrapping synchronous/blocking code in async methods
› The continuation is on the calling thread!
› Async lambdas: async () => { await Task.Delay(2000); }
Page 15 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Page
Page16 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Summary
› Async is powerful
› Using Async wrong may deadlock your application
› Can be hard to debug
› Await all your tasks to verify the execution!
Page 17 / Copyright ©2014 by Readify Pty Ltd
@fekberg
Questions?
Page 18 / Copyright ©2014 by Readify Pty Ltd
Thank you!
[email protected]
http://fekberg.com
+61 (401) 157-608
@fekberg
C# Smorgasbord
Page 19 / Copyright ©2014 by Readify Pty Ltd