6. Asynchrony is…
about results that are delayed, and yielding
control while awaiting their results (co-operative
multitasking).
Good reasons to use asynchrony:
• for overall control / coordination structure of a
program
• for UI responsiveness
• for IO- and network-bound code
7. Trends
• Increasingly connected applications
– More latency
– More UI responsiveness problems
– More scalability issues
• Asynchronous programming
– Becoming the norm in responsive, scalable
apps
– Async-only APIs, e.g., Silverlight
8. A bit of evolution
C# + VB 4.5
Asynchronous
Programming
C# 4.0 + VB 10.0 C# and VB Evolution
Dynamic +
Language Parity
C# 3.0 + VB 9.0
Language Integrated
Query
C# 2.0 + VB 8.0
Generics
C# 1.0 + VB 7.0
Managed Code
9. A bit of evolution
•
•
•
•
Synchronous programming
APM – Asynchronous Programming Model
EAP – Event Asynchronous Pattern
Async (TAP) – Task Asynchronous Pattern
18. Task returning vs void
returning
async Task FooAsync(…);
async void Foo_Click(…);
•
•
•
Can be awaited
“Give back control”
Delegate asynchronous work
•
•
•
Cannot be awaited
“Fire and forget”
Start separate independent flow
•
•
Use for helper methods
Use for library methods
•
•
Use for event handlers
Use to override void methods
20. “A waiter’s job is to wait on a table until the patrons have finished their meal.
If you want to serve two tables concurrently, you must hire two waiters.”
24. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
25. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
26. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
27. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
28. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
29. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
30. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
31. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
32. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
33. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
34. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
35. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
36. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
37. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
38. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
39. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
40. Asynchronous Control Flow
async void DoWorkAsync() {
var t1 = ProcessFeedAsync("www.acme.com/rss");
var t2 = ProcessFeedAsync("www.xyznews.com/rss");
await Task.WhenAll(t1, t2);
DisplayMessage("Done");
}
async Task ProcessFeedAsync(string url) {
var text = await DownloadFeedAsync(url);
var doc = ParseFeedIntoDoc(text);
await SaveDocAsync(doc);
ProcessLog.WriteEntry(url);
}
41. What have we seen?
•
•
•
•
•
Importance of Asynchronous
Async/Await basics
Tasks
Synchronization
Flow
42. Comparing TAP to its
predecessors
// Task Asynchronous Pattern [TAP], with Cancellation and Progress
Task<TR> GetStringAsync(Params..., [CancellationToken Cancel],
[IProgress<TP> Progress])
// Asynchronous Programming Model [APM]
IAsyncResult BeginGetString(Params..., AsyncCallback Callback, object state);
TR EndGetString(IAsyncResult);
// Event-based Asynchronous Pattern [EAP]
class C
{
public void GetStringAsync(Params...);
public event GetStringCompletedEventHandler GetStringCompleted;
public void CancelAsync();
}
class GetStringCompletedEventArgs
{
public TR Result { get; }
public Exception Error { get; }
}
43. Some facts
• Most of the Async methods will complete
Synchronously. They will use a thread only
when really necessary.
• It’s good to minimize the use of Awaits, using
combinators is good (eg, Task.WhenAll).
Be water, my friend!Asynchronous operations can share a single thread for multiple control flowsThe UI and IOCP threads are provided by the CLR or OS – reuseCo-Operative multitasking. Wait for tasks to finish and yield control flow while awaiting.
We initially hadvar task2 = task.TimeoutAfter(1000);But we removed it because it didn’t have a clear-enough design. Would you want task2 to end with an OperationCancelledException after 1000ms? Or to end successfully? Both forms are useful. In the end, we figured that cancellation-after-1000ms was easier done like this:var cts = new CancellationTokenSource();cts.CancelAfter(1000)And we figured that successful-termination-after-1000ms was clearer if you wrote it out manually:var task2 = task.WhenAny(task, Task.Delay(1000))