SlideShare a Scribd company logo
xedotnet.org
Async Debugging
A Practical Guide to survive !
Mirco Vanini
@MircoVanini
Agenda
• Sync To Async Code
• Async state machine
• Async logical call stack (chain of continuations)
• Debug
• Parallel Stacks for Tasks and Theads
• Tasks Window
• Threads Window
• Parallel Watch
• Rethrown Exceptions
• Snapshot on Exception (IntelliTrace -> Historical Debugger)
• Async Guidance
• Q&A
Start plain and simple
public double GetTotalOderedByCustomer(string customer)
{
double total = 0;
foreach (var order in GetOrdersByCustomer(customer))
{
var details = order.GetOrderDetails();
total += details.Sum(d => d.Quantity * d.UnitPrice);
}
return total;
}
Everythings is frozen and
we are doomed !
…How about adding
some async/await ?
Compiler generated code
public async Task<double> GetTotalOderedByCustomerAsync(string customer)
{
double total = 0;
foreach (var order in await GetOrdersByCustomerAsync(customer))
{
var details = await order.GetOrderDetailsAsync();
total += details.Sum(d => d.Quantity * d.UnitPrice);
}
return total;
}
[AsyncStateMachine(typeof(<GetTotalOderedByCustomerAsync>d__0))]
[DebuggerStepThrough]
public Task<double> GetTotalOderedByCustomerAsync(string customer)
{
<GetTotalOderedByCustomerAsync>d__0 stateMachine = new
<GetTotalOderedByCustomerAsync>d__0();
stateMachine.<>t__builder = AsyncTaskMethodBuilder<double>.Create();
stateMachine.<>4__this = this;
stateMachine.customer = customer;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
SharpLab.io
Compiler generated code
public async Task<double>
GetTotalOderedByCustomerAsync(string customer)
{
double total = 0;
foreach (var order in await
GetOrdersByCustomerAsync(customer))
{
var details = await order.GetOrderDetailsAsync();
total += details.Sum(d => d.Quantity *
d.UnitPrice);
}
return total;
}
[CompilerGenerated]
private sealed class <GetTotalOderedByCustomerAsync>d__0 : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder<double> <>t__builder;
// local variables !
public string customer;
public DataService <>4__this;
private double <total>5__1;
...
// awaiters !
private TaskAwaiter<IEnumerable<Order>> <>u__1;
private TaskAwaiter<IEnumerable<OrderDetail>> <>u__2;
private void MoveNext()
{
int num = <>1__state;
double result;
try
{
TaskAwaiter<IEnumerable<Order>> awaiter;
if (num != 0)
{
if (num == 1)
{
goto IL_00c4;
}
<total>5__1 = 0.0;
awaiter = <>4__this.GetOrdersByCustomerAsync(customer).GetAwaiter();
SharpLab.io
Performance ?
Without Await | I/O-bound vs CPU-bound
public Task<double> GetTotalOderedByCustomerWithoutAwait(string customer)
{
ConcurrentBag<double> totals = new ConcurrentBag<double>();
Task<IEnumerable<Order>> fetchOrders = Task.Run(() => GetOrdersByCustomer(customer));
Task matchOrders = fetchOrders.ContinueWith(t =>
{
List<Task> matchTasks = new();
foreach (var order in t.Result)
{
Task<IEnumerable<OrderDetail>> detailTask = Task.Run(() => order.GetOrderDetails());
Task matchDetail = detailTask.ContinueWith(t1 =>
{
totals.Add(t1.Result.Sum(d => d.Quantity * d.UnitPrice));
}, TaskContinuationOptions.AttachedToParent);
matchTasks.Add(matchDetail);
}
return Task.WhenAll(matchTasks);
});
return matchOrders.ContinueWith(_ => totals.Sum(p => p));
}
Async code | call stack
Debug > Windows > Call stack | Debug > Windows > Threads > main thread)
Async code | call stack
Debug > Windows > Parallel Stacks > Threads
So how do we debug this ?
Async logical call stack
The first thing used while debugging are «call stacks»
Call stack show caller -> callee relation !
We also need call stack fro async code – such as «async call stacks»
Async vs sync stacks
SYNC stacks ASYNC stacks
Code is currently running on a thread Code may not be running anywhere or
scheduled to run in the future
Hence – Physical stacks Virtual or logical stacks. Not tied to a single
(or any) thread.
Locals are allocated on stack memory Local are stashed in “state machines” (internal
compiler generated helper structures)
Async call stacks
Task #1
GetOrderByCustomerAsync()
m_continuation
public async Task<double> GetTotalOderedByCustomerAsync(string customer)
{
double total = 0;
foreach (var order in await GetOrdersByCustomerAsync(customer))
{
var details = await order.GetOrderDetailsAsync();
total += details.Sum(d => d.Quantity * d.UnitPrice);
}
return total;
}
Task #2
GetOrderDetailsAsync()
m_continuation
Here the await keyword adds the next line of GetTotalOrderedByCutomerAsync
as a continuation to GetOrdersByCustomerAsync.
The Task of GetOderDetailsAsync store a reference to the next line of
GetTotalOrderedByCutomerAsync to invoke when done.
Async call stacks
Task #1
GetOrderByCustomerAsync()
m_continuation
Task #2
GetOrderDetailsAsync()
m_continuation
The debugger walks through this chain of references – to get a chain of
continuations
Async Logical Stacks
GetOrderDetailsAsync
GetOrderByCustomerAsync
The chian of continuations is what we call async call stack
Async call stacks
Task #1
GetOrderByCustomerAsync()
m_continuation
Task #2
GetOrderDetailsAsync()
m_continuation
Async stack are a continuation stack
This may be quite different from the stack or context of where the task
was created – that is, the creation stack
Task #N
...
m_continuation
Creation Stack vs Continuation Stack
Note that TakeABreak is not part of the async call stack
Async Task
> Task.Delay(…)
DoSomething(…)
public Task TakeABreak()
{
return Task.Delay(1000);
}
public async Task DoSomething()
{
foreach (var order in orders)
{
Task pause = TakeABreak();
details = await order.GetOrderDetails();
await pause;
}
}
??? TakeABreak(…) ???
Creation Stack vs Continuation Stack
Sync call stack are also really just continuation stack: the creation (call) and
continuation are the same
In async, control goes to whoever awaits (or waits) the current async code,
which may be different from the scope or method in which it was called.
Keep that in mind while async debugging – especially while using
TaskCompletitionSource<T> [used for APM (Asynchronous Programming Model)
or EAP (Event-Based Asynchronous Pattern)].
EAP sample
public static class StoryboardHelper
{
public static Task RunAsync(this Storyboard storyboard)
{
var tcs = new TaskCompletionSource<object>();
EventHandler<object> completion = null;
completion = (sender, args) =>
{
storyboard.Completed -= completion;
tcs.SetResult(null);
};
storyboard.Completed += completion;
storyboard.Begin();
return tcs.Task;
}
}
…
await myStoryboard.RunAsync();
Async call stacks
public async Task DoSomething()
{
List<Task> tasks = new List<Task>();
foreach (var order in orders)
{
tasks.Add(order.GetOrderDetailsAsync());
}
await Task.WhenAll(tasks);
}
Task #1
GetOrderDetailsAsync()
m_continuation
Task #2
GetOrderDetailsAsync()
m_continuation
Task #2
GetOrderDetailsAsync()
m_continuation
Task #1
DoSomething()
m_continuation
Demo | Parallel Stacks for Tasks and Theads
Demo | Tasks Window – Threads Window
Demo | Rethrown Exceptions / Snapshot on Exception
Async Code Tips
• Async void
• Prefer Task.FromResult over Task.Run for pre-computed or trivially computed data
• Avoid using Task.Run for long running work that blocks the thread
• Avoid using Task.Result and Task.Wait
• Prefer await over ContinueWith
• Always create TaskCompletionSource<T> with TaskCreationOptions.RunContinuationsAsynchronously
• Always dispose CancellationTokenSource(s) used for timeouts
• Always flow CancellationToken(s) to APIs that take a CancellationToken
• Cancelling uncancellable operations
• Always call FlushAsync on StreamWriter(s) or Stream(s) before calling Dispose
• Prefer async/await over directly returning Task
• ConfigureAwait
The first debugging step is writing good code !
AsyncGuidance
Q&A
.NET
your platform for building anything
Mirco Vanini
Microsoft® MVP Windows Development
myContactInfo:
{
”e-mail”:“mirco.vanini@proxsoft.it”,
“web”: “www.proxsoft.it”,
“twitter”: “@MircoVanini”
}

More Related Content

What's hot

Reactive server with netty
Reactive server with nettyReactive server with netty
Reactive server with netty
Dmitriy Dumanskiy
 
Exploring Twitter's Finagle technology stack for microservices
Exploring Twitter's Finagle technology stack for microservicesExploring Twitter's Finagle technology stack for microservices
Exploring Twitter's Finagle technology stack for microservices
đź’ˇ Tomasz Kogut
 
Tale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark StreamingTale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark Streaming
Sigmoid
 
RBuilder and ByteSurgeon
RBuilder and ByteSurgeonRBuilder and ByteSurgeon
RBuilder and ByteSurgeon
Marcus Denker
 
Monitoring with Prometheus
Monitoring with PrometheusMonitoring with Prometheus
Monitoring with Prometheus
Shiao-An Yuan
 
Powershell Seminar @ ITWorx CuttingEdge Club
Powershell Seminar @ ITWorx CuttingEdge ClubPowershell Seminar @ ITWorx CuttingEdge Club
Powershell Seminar @ ITWorx CuttingEdge Club
Essam Salah
 
Internship final report@Treasure Data Inc.
Internship final report@Treasure Data Inc.Internship final report@Treasure Data Inc.
Internship final report@Treasure Data Inc.
Ryuichi ITO
 
Reactive programming with examples
Reactive programming with examplesReactive programming with examples
Reactive programming with examples
Peter Lawrey
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
Pavan Chitumalla
 
Asynchronous, Event-driven Network Application Development with Netty
Asynchronous, Event-driven Network Application Development with NettyAsynchronous, Event-driven Network Application Development with Netty
Asynchronous, Event-driven Network Application Development with Netty
Ersin Er
 
Apache Flink Stream Processing
Apache Flink Stream ProcessingApache Flink Stream Processing
Apache Flink Stream Processing
Suneel Marthi
 
Dynamo: Not Just For Datastores
Dynamo: Not Just For DatastoresDynamo: Not Just For Datastores
Dynamo: Not Just For Datastores
Susan Potter
 
Implementações paralelas
Implementações paralelasImplementações paralelas
Implementações paralelas
Willian Molinari
 
Better Open Source Enterprise C++ Web Services
Better Open Source Enterprise C++ Web ServicesBetter Open Source Enterprise C++ Web Services
Better Open Source Enterprise C++ Web Services
WSO2
 
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
ucelebi
 
Pulsar connector on flink 1.14
Pulsar connector on flink 1.14Pulsar connector on flink 1.14
Pulsar connector on flink 1.14
宇帆 盛
 
Pune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCDPune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCD
Prashant Rane
 
In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QML
ICS
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
Kasun Indrasiri
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVM
Min-Yih Hsu
 

What's hot (20)

Reactive server with netty
Reactive server with nettyReactive server with netty
Reactive server with netty
 
Exploring Twitter's Finagle technology stack for microservices
Exploring Twitter's Finagle technology stack for microservicesExploring Twitter's Finagle technology stack for microservices
Exploring Twitter's Finagle technology stack for microservices
 
Tale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark StreamingTale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark Streaming
 
RBuilder and ByteSurgeon
RBuilder and ByteSurgeonRBuilder and ByteSurgeon
RBuilder and ByteSurgeon
 
Monitoring with Prometheus
Monitoring with PrometheusMonitoring with Prometheus
Monitoring with Prometheus
 
Powershell Seminar @ ITWorx CuttingEdge Club
Powershell Seminar @ ITWorx CuttingEdge ClubPowershell Seminar @ ITWorx CuttingEdge Club
Powershell Seminar @ ITWorx CuttingEdge Club
 
Internship final report@Treasure Data Inc.
Internship final report@Treasure Data Inc.Internship final report@Treasure Data Inc.
Internship final report@Treasure Data Inc.
 
Reactive programming with examples
Reactive programming with examplesReactive programming with examples
Reactive programming with examples
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
Asynchronous, Event-driven Network Application Development with Netty
Asynchronous, Event-driven Network Application Development with NettyAsynchronous, Event-driven Network Application Development with Netty
Asynchronous, Event-driven Network Application Development with Netty
 
Apache Flink Stream Processing
Apache Flink Stream ProcessingApache Flink Stream Processing
Apache Flink Stream Processing
 
Dynamo: Not Just For Datastores
Dynamo: Not Just For DatastoresDynamo: Not Just For Datastores
Dynamo: Not Just For Datastores
 
Implementações paralelas
Implementações paralelasImplementações paralelas
Implementações paralelas
 
Better Open Source Enterprise C++ Web Services
Better Open Source Enterprise C++ Web ServicesBetter Open Source Enterprise C++ Web Services
Better Open Source Enterprise C++ Web Services
 
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
Apache Flink Internals: Stream & Batch Processing in One System – Apache Flin...
 
Pulsar connector on flink 1.14
Pulsar connector on flink 1.14Pulsar connector on flink 1.14
Pulsar connector on flink 1.14
 
Pune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCDPune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCD
 
In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QML
 
Reactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-JavaReactive Programming in Java 8 with Rx-Java
Reactive Programming in Java 8 with Rx-Java
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVM
 

Similar to Async Debugging A Practical Guide to survive !

Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio
 
Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
PeckaDesign.cz
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
Garrett Welson
 
Concurrency at the Database Layer
Concurrency at the Database Layer Concurrency at the Database Layer
Concurrency at the Database Layer
mcwilson1
 
Why async matters
Why async mattersWhy async matters
Why async matters
timbc
 
Programming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for AndroidProgramming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for Android
Emanuele Di Saverio
 
Threaded Programming
Threaded ProgrammingThreaded Programming
Threaded ProgrammingSri Prasanna
 
Spark streaming with kafka
Spark streaming with kafkaSpark streaming with kafka
Spark streaming with kafka
Dori Waldman
 
Spark stream - Kafka
Spark stream - Kafka Spark stream - Kafka
Spark stream - Kafka
Dori Waldman
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
Karel Zikmund
 
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel ZikmundNDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
Karel Zikmund
 
Sync with async
Sync with  asyncSync with  async
Sync with async
prabathsl
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
Task parallel library presentation
Task parallel library presentationTask parallel library presentation
Task parallel library presentation
ahmed sayed
 
What the CRaC - Superfast JVM startup
What the CRaC - Superfast JVM startupWhat the CRaC - Superfast JVM startup
What the CRaC - Superfast JVM startup
Gerrit Grunwald
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
Piotr Pelczar
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
Chetan Giridhar
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)jeffz
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
Bartosz Sypytkowski
 
Async fun
Async funAsync fun

Similar to Async Debugging A Practical Guide to survive ! (20)

Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
 
Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Concurrency at the Database Layer
Concurrency at the Database Layer Concurrency at the Database Layer
Concurrency at the Database Layer
 
Why async matters
Why async mattersWhy async matters
Why async matters
 
Programming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for AndroidProgramming Sideways: Asynchronous Techniques for Android
Programming Sideways: Asynchronous Techniques for Android
 
Threaded Programming
Threaded ProgrammingThreaded Programming
Threaded Programming
 
Spark streaming with kafka
Spark streaming with kafkaSpark streaming with kafka
Spark streaming with kafka
 
Spark stream - Kafka
Spark stream - Kafka Spark stream - Kafka
Spark stream - Kafka
 
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
.NET Core Summer event 2019 in Brno, CZ - Async demystified -- Karel Zikmund
 
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel ZikmundNDC Sydney 2019 - Async Demystified -- Karel Zikmund
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
 
Sync with async
Sync with  asyncSync with  async
Sync with async
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Task parallel library presentation
Task parallel library presentationTask parallel library presentation
Task parallel library presentation
 
What the CRaC - Superfast JVM startup
What the CRaC - Superfast JVM startupWhat the CRaC - Superfast JVM startup
What the CRaC - Superfast JVM startup
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
Async programming and python
Async programming and pythonAsync programming and python
Async programming and python
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
Async fun
Async funAsync fun
Async fun
 

More from Mirco Vanini

.NET 7 Performance Improvements_10_03_2023.pdf
.NET 7 Performance Improvements_10_03_2023.pdf.NET 7 Performance Improvements_10_03_2023.pdf
.NET 7 Performance Improvements_10_03_2023.pdf
Mirco Vanini
 
Debugging a .NET program after crash (Post-mortem debugging)
Debugging a .NET program after crash (Post-mortem debugging)Debugging a .NET program after crash (Post-mortem debugging)
Debugging a .NET program after crash (Post-mortem debugging)
Mirco Vanini
 
Connect a chips to Azure
Connect a chips to AzureConnect a chips to Azure
Connect a chips to Azure
Mirco Vanini
 
Connect a chips to Azure
Connect a chips to AzureConnect a chips to Azure
Connect a chips to Azure
Mirco Vanini
 
How to modernise WPF and Windows Forms applications with Windows Apps SDK
How to modernise WPF and Windows Forms applications with Windows Apps SDKHow to modernise WPF and Windows Forms applications with Windows Apps SDK
How to modernise WPF and Windows Forms applications with Windows Apps SDK
Mirco Vanini
 
C# on a CHIPs
C# on a CHIPsC# on a CHIPs
C# on a CHIPs
Mirco Vanini
 
.NET Conf 2021 - Hot Topics Desktop Development
.NET Conf 2021 - Hot Topics Desktop Development.NET Conf 2021 - Hot Topics Desktop Development
.NET Conf 2021 - Hot Topics Desktop Development
Mirco Vanini
 
IoT support for .NET (Core/5/6)
IoT support for .NET (Core/5/6)IoT support for .NET (Core/5/6)
IoT support for .NET (Core/5/6)
Mirco Vanini
 
IoT support for .NET Core
IoT support for .NET CoreIoT support for .NET Core
IoT support for .NET Core
Mirco Vanini
 
IoT support for .NET Core - IoT Saturday 2020
IoT support for .NET Core - IoT Saturday 2020IoT support for .NET Core - IoT Saturday 2020
IoT support for .NET Core - IoT Saturday 2020
Mirco Vanini
 
.NET Conf 2020 - Hot Topics Desktop Development
.NET Conf 2020 - Hot Topics Desktop Development.NET Conf 2020 - Hot Topics Desktop Development
.NET Conf 2020 - Hot Topics Desktop Development
Mirco Vanini
 
Are you ready for Microsoft Azure Sphere?
Are you ready for Microsoft Azure Sphere?Are you ready for Microsoft Azure Sphere?
Are you ready for Microsoft Azure Sphere?
Mirco Vanini
 
IoT Day 2019 Naples - Microsoft Azure Shpere
IoT Day 2019 Naples - Microsoft Azure ShpereIoT Day 2019 Naples - Microsoft Azure Shpere
IoT Day 2019 Naples - Microsoft Azure Shpere
Mirco Vanini
 
Debugging with VS2019
Debugging with VS2019Debugging with VS2019
Debugging with VS2019
Mirco Vanini
 
Azure Sphere
Azure SphereAzure Sphere
Azure Sphere
Mirco Vanini
 
Optimising code using Span<T>
Optimising code using Span<T>Optimising code using Span<T>
Optimising code using Span<T>
Mirco Vanini
 
Azure Sphere
Azure SphereAzure Sphere
Azure Sphere
Mirco Vanini
 
Xe OneDay - Modernizing Enterprise Apps
Xe OneDay - Modernizing Enterprise AppsXe OneDay - Modernizing Enterprise Apps
Xe OneDay - Modernizing Enterprise Apps
Mirco Vanini
 
Azure Sphere - GAB 2019
Azure Sphere - GAB 2019Azure Sphere - GAB 2019
Azure Sphere - GAB 2019
Mirco Vanini
 
IoT Day - Introducing Azure Sphere
IoT Day -  Introducing Azure SphereIoT Day -  Introducing Azure Sphere
IoT Day - Introducing Azure Sphere
Mirco Vanini
 

More from Mirco Vanini (20)

.NET 7 Performance Improvements_10_03_2023.pdf
.NET 7 Performance Improvements_10_03_2023.pdf.NET 7 Performance Improvements_10_03_2023.pdf
.NET 7 Performance Improvements_10_03_2023.pdf
 
Debugging a .NET program after crash (Post-mortem debugging)
Debugging a .NET program after crash (Post-mortem debugging)Debugging a .NET program after crash (Post-mortem debugging)
Debugging a .NET program after crash (Post-mortem debugging)
 
Connect a chips to Azure
Connect a chips to AzureConnect a chips to Azure
Connect a chips to Azure
 
Connect a chips to Azure
Connect a chips to AzureConnect a chips to Azure
Connect a chips to Azure
 
How to modernise WPF and Windows Forms applications with Windows Apps SDK
How to modernise WPF and Windows Forms applications with Windows Apps SDKHow to modernise WPF and Windows Forms applications with Windows Apps SDK
How to modernise WPF and Windows Forms applications with Windows Apps SDK
 
C# on a CHIPs
C# on a CHIPsC# on a CHIPs
C# on a CHIPs
 
.NET Conf 2021 - Hot Topics Desktop Development
.NET Conf 2021 - Hot Topics Desktop Development.NET Conf 2021 - Hot Topics Desktop Development
.NET Conf 2021 - Hot Topics Desktop Development
 
IoT support for .NET (Core/5/6)
IoT support for .NET (Core/5/6)IoT support for .NET (Core/5/6)
IoT support for .NET (Core/5/6)
 
IoT support for .NET Core
IoT support for .NET CoreIoT support for .NET Core
IoT support for .NET Core
 
IoT support for .NET Core - IoT Saturday 2020
IoT support for .NET Core - IoT Saturday 2020IoT support for .NET Core - IoT Saturday 2020
IoT support for .NET Core - IoT Saturday 2020
 
.NET Conf 2020 - Hot Topics Desktop Development
.NET Conf 2020 - Hot Topics Desktop Development.NET Conf 2020 - Hot Topics Desktop Development
.NET Conf 2020 - Hot Topics Desktop Development
 
Are you ready for Microsoft Azure Sphere?
Are you ready for Microsoft Azure Sphere?Are you ready for Microsoft Azure Sphere?
Are you ready for Microsoft Azure Sphere?
 
IoT Day 2019 Naples - Microsoft Azure Shpere
IoT Day 2019 Naples - Microsoft Azure ShpereIoT Day 2019 Naples - Microsoft Azure Shpere
IoT Day 2019 Naples - Microsoft Azure Shpere
 
Debugging with VS2019
Debugging with VS2019Debugging with VS2019
Debugging with VS2019
 
Azure Sphere
Azure SphereAzure Sphere
Azure Sphere
 
Optimising code using Span<T>
Optimising code using Span<T>Optimising code using Span<T>
Optimising code using Span<T>
 
Azure Sphere
Azure SphereAzure Sphere
Azure Sphere
 
Xe OneDay - Modernizing Enterprise Apps
Xe OneDay - Modernizing Enterprise AppsXe OneDay - Modernizing Enterprise Apps
Xe OneDay - Modernizing Enterprise Apps
 
Azure Sphere - GAB 2019
Azure Sphere - GAB 2019Azure Sphere - GAB 2019
Azure Sphere - GAB 2019
 
IoT Day - Introducing Azure Sphere
IoT Day -  Introducing Azure SphereIoT Day -  Introducing Azure Sphere
IoT Day - Introducing Azure Sphere
 

Recently uploaded

GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Vladimir Iglovikov, Ph.D.
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 

Recently uploaded (20)

GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 

Async Debugging A Practical Guide to survive !

  • 1. xedotnet.org Async Debugging A Practical Guide to survive ! Mirco Vanini @MircoVanini
  • 2. Agenda • Sync To Async Code • Async state machine • Async logical call stack (chain of continuations) • Debug • Parallel Stacks for Tasks and Theads • Tasks Window • Threads Window • Parallel Watch • Rethrown Exceptions • Snapshot on Exception (IntelliTrace -> Historical Debugger) • Async Guidance • Q&A
  • 3. Start plain and simple public double GetTotalOderedByCustomer(string customer) { double total = 0; foreach (var order in GetOrdersByCustomer(customer)) { var details = order.GetOrderDetails(); total += details.Sum(d => d.Quantity * d.UnitPrice); } return total; } Everythings is frozen and we are doomed ! …How about adding some async/await ?
  • 4. Compiler generated code public async Task<double> GetTotalOderedByCustomerAsync(string customer) { double total = 0; foreach (var order in await GetOrdersByCustomerAsync(customer)) { var details = await order.GetOrderDetailsAsync(); total += details.Sum(d => d.Quantity * d.UnitPrice); } return total; } [AsyncStateMachine(typeof(<GetTotalOderedByCustomerAsync>d__0))] [DebuggerStepThrough] public Task<double> GetTotalOderedByCustomerAsync(string customer) { <GetTotalOderedByCustomerAsync>d__0 stateMachine = new <GetTotalOderedByCustomerAsync>d__0(); stateMachine.<>t__builder = AsyncTaskMethodBuilder<double>.Create(); stateMachine.<>4__this = this; stateMachine.customer = customer; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } SharpLab.io
  • 5. Compiler generated code public async Task<double> GetTotalOderedByCustomerAsync(string customer) { double total = 0; foreach (var order in await GetOrdersByCustomerAsync(customer)) { var details = await order.GetOrderDetailsAsync(); total += details.Sum(d => d.Quantity * d.UnitPrice); } return total; } [CompilerGenerated] private sealed class <GetTotalOderedByCustomerAsync>d__0 : IAsyncStateMachine { public int <>1__state; public AsyncTaskMethodBuilder<double> <>t__builder; // local variables ! public string customer; public DataService <>4__this; private double <total>5__1; ... // awaiters ! private TaskAwaiter<IEnumerable<Order>> <>u__1; private TaskAwaiter<IEnumerable<OrderDetail>> <>u__2; private void MoveNext() { int num = <>1__state; double result; try { TaskAwaiter<IEnumerable<Order>> awaiter; if (num != 0) { if (num == 1) { goto IL_00c4; } <total>5__1 = 0.0; awaiter = <>4__this.GetOrdersByCustomerAsync(customer).GetAwaiter(); SharpLab.io
  • 7. Without Await | I/O-bound vs CPU-bound public Task<double> GetTotalOderedByCustomerWithoutAwait(string customer) { ConcurrentBag<double> totals = new ConcurrentBag<double>(); Task<IEnumerable<Order>> fetchOrders = Task.Run(() => GetOrdersByCustomer(customer)); Task matchOrders = fetchOrders.ContinueWith(t => { List<Task> matchTasks = new(); foreach (var order in t.Result) { Task<IEnumerable<OrderDetail>> detailTask = Task.Run(() => order.GetOrderDetails()); Task matchDetail = detailTask.ContinueWith(t1 => { totals.Add(t1.Result.Sum(d => d.Quantity * d.UnitPrice)); }, TaskContinuationOptions.AttachedToParent); matchTasks.Add(matchDetail); } return Task.WhenAll(matchTasks); }); return matchOrders.ContinueWith(_ => totals.Sum(p => p)); }
  • 8. Async code | call stack Debug > Windows > Call stack | Debug > Windows > Threads > main thread)
  • 9. Async code | call stack Debug > Windows > Parallel Stacks > Threads
  • 10. So how do we debug this ? Async logical call stack The first thing used while debugging are «call stacks» Call stack show caller -> callee relation ! We also need call stack fro async code – such as «async call stacks»
  • 11. Async vs sync stacks SYNC stacks ASYNC stacks Code is currently running on a thread Code may not be running anywhere or scheduled to run in the future Hence – Physical stacks Virtual or logical stacks. Not tied to a single (or any) thread. Locals are allocated on stack memory Local are stashed in “state machines” (internal compiler generated helper structures)
  • 12. Async call stacks Task #1 GetOrderByCustomerAsync() m_continuation public async Task<double> GetTotalOderedByCustomerAsync(string customer) { double total = 0; foreach (var order in await GetOrdersByCustomerAsync(customer)) { var details = await order.GetOrderDetailsAsync(); total += details.Sum(d => d.Quantity * d.UnitPrice); } return total; } Task #2 GetOrderDetailsAsync() m_continuation Here the await keyword adds the next line of GetTotalOrderedByCutomerAsync as a continuation to GetOrdersByCustomerAsync. The Task of GetOderDetailsAsync store a reference to the next line of GetTotalOrderedByCutomerAsync to invoke when done.
  • 13. Async call stacks Task #1 GetOrderByCustomerAsync() m_continuation Task #2 GetOrderDetailsAsync() m_continuation The debugger walks through this chain of references – to get a chain of continuations Async Logical Stacks GetOrderDetailsAsync GetOrderByCustomerAsync The chian of continuations is what we call async call stack
  • 14. Async call stacks Task #1 GetOrderByCustomerAsync() m_continuation Task #2 GetOrderDetailsAsync() m_continuation Async stack are a continuation stack This may be quite different from the stack or context of where the task was created – that is, the creation stack Task #N ... m_continuation
  • 15. Creation Stack vs Continuation Stack Note that TakeABreak is not part of the async call stack Async Task > Task.Delay(…) DoSomething(…) public Task TakeABreak() { return Task.Delay(1000); } public async Task DoSomething() { foreach (var order in orders) { Task pause = TakeABreak(); details = await order.GetOrderDetails(); await pause; } } ??? TakeABreak(…) ???
  • 16. Creation Stack vs Continuation Stack Sync call stack are also really just continuation stack: the creation (call) and continuation are the same In async, control goes to whoever awaits (or waits) the current async code, which may be different from the scope or method in which it was called. Keep that in mind while async debugging – especially while using TaskCompletitionSource<T> [used for APM (Asynchronous Programming Model) or EAP (Event-Based Asynchronous Pattern)].
  • 17. EAP sample public static class StoryboardHelper { public static Task RunAsync(this Storyboard storyboard) { var tcs = new TaskCompletionSource<object>(); EventHandler<object> completion = null; completion = (sender, args) => { storyboard.Completed -= completion; tcs.SetResult(null); }; storyboard.Completed += completion; storyboard.Begin(); return tcs.Task; } } … await myStoryboard.RunAsync();
  • 18. Async call stacks public async Task DoSomething() { List<Task> tasks = new List<Task>(); foreach (var order in orders) { tasks.Add(order.GetOrderDetailsAsync()); } await Task.WhenAll(tasks); } Task #1 GetOrderDetailsAsync() m_continuation Task #2 GetOrderDetailsAsync() m_continuation Task #2 GetOrderDetailsAsync() m_continuation Task #1 DoSomething() m_continuation
  • 19. Demo | Parallel Stacks for Tasks and Theads
  • 20. Demo | Tasks Window – Threads Window
  • 21. Demo | Rethrown Exceptions / Snapshot on Exception
  • 22. Async Code Tips • Async void • Prefer Task.FromResult over Task.Run for pre-computed or trivially computed data • Avoid using Task.Run for long running work that blocks the thread • Avoid using Task.Result and Task.Wait • Prefer await over ContinueWith • Always create TaskCompletionSource<T> with TaskCreationOptions.RunContinuationsAsynchronously • Always dispose CancellationTokenSource(s) used for timeouts • Always flow CancellationToken(s) to APIs that take a CancellationToken • Cancelling uncancellable operations • Always call FlushAsync on StreamWriter(s) or Stream(s) before calling Dispose • Prefer async/await over directly returning Task • ConfigureAwait The first debugging step is writing good code ! AsyncGuidance
  • 23. Q&A .NET your platform for building anything Mirco Vanini Microsoft® MVP Windows Development myContactInfo: { ”e-mail”:“mirco.vanini@proxsoft.it”, “web”: “www.proxsoft.it”, “twitter”: “@MircoVanini” }