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 ReportTranscript 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