Pavel Yosifovich Hi-Tech College
C# Evolution Trends Synchronous vs. Asynchronous Asynchrony the “old way” The New Way Odds and Ends Summary
C# 1.0 Managed Code C# 2.0 Generics C# 3.0 Language Integrated Query C# 4.0 Dynamic Typing
Declarative ConcurrentDynamic
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. JavaScript and Silverlight
C# 1.0 Managed Code C# 2.0 Generics C# 3.0 Language Integrated Query C# 4.0 Dynamic Typing Asynchronous Programming C# v.Next
Synchronous Wait for result before returning string DownloadString(...); Asynchronous Return now, call back with result void DownloadStringAsync(..., Action callback); Asynchronous work != Threads
var data = DownloadData(...); ProcessData(data); var data = DownloadData(...); ProcessData(data); DownloadDataAsync(..., data => { ProcessData(data); }); DownloadDataAsync(..., data => { ProcessData(data); });
var data = DownloadData(...); ProcessData(data); var data = DownloadData(...); ProcessData(data); DownloadDataAsync(..., data => { ProcessData(data); }); DownloadDataAsync(..., data => { ProcessData(data); });
Goal: Just like synchronous programming Framework: Use Task for all asynchrony Add Task support to existing.NET and Silverlight APIs Developers can do the same Languages: Asynchronous Methods “async” modifier marks method or lambda as asynchronous “await” operator yields control until awaited task completes
Represents “ongoing operation” Could be async I/O, background worker, anything... Single object for status, result and exceptions Composable callback model var task2 = task1.ContinueWith(t => … t.Result …); The “await” operator rewrites to continuations Combinators WhenAll, WhenAny, Delay, etc.
async void DoWorkAsync() { var t1 = ProcessFeedAsync(" var t2 = ProcessFeedAsync(" await Task.WhenAll(t1, t2); DisplayMessage("Done"); } async void DoWorkAsync() { var t1 = ProcessFeedAsync(" var t2 = ProcessFeedAsync(" 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); } async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url); }
async void DoWorkAsync() { var t1 = ProcessFeedAsync(" var t2 = ProcessFeedAsync(" await Task.WhenAll(t1, t2); DisplayMessage("Done"); } async void DoWorkAsync() { var t1 = ProcessFeedAsync(" var t2 = ProcessFeedAsync(" 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); } async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url); }
async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url); } async Task ProcessFeedAsync(string url) { var text = await DownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); await SaveDocAsync(doc); ProcessLog.WriteEntry(url); }
Should be as simple as the synchronous case var wc = new WebClient(); try { string txt = await wc.DownloadStringTaskAsync(url); dataTextBox.Text = txt; } catch(WebException x) { // Handle as usual } var wc = new WebClient(); try { string txt = await wc.DownloadStringTaskAsync(url); dataTextBox.Text = txt; } catch(WebException x) { // Handle as usual }
async Task GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; } async Task GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; }
async Task GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; } async Task GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; } Task GetRssAsync(string url) { var $builder = AsyncMethodBuilder.Create(); var $state = 0; TaskAwaiter $a1; Action $resume = delegate { try { if ($state == 1) goto L1; var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); $state = 1; $a1 = task.GetAwaiter(); if ($a1.BeginAwait($resume)) return; L1: var text = $a1.EndAwait(); var xml = XElement.Parse(text); $builder.SetResult(xml); } catch (Exception $ex) { $builder.SetException($ex); } }; $resume(); return $builder.Task; } Task GetRssAsync(string url) { var $builder = AsyncMethodBuilder.Create(); var $state = 0; TaskAwaiter $a1; Action $resume = delegate { try { if ($state == 1) goto L1; var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); $state = 1; $a1 = task.GetAwaiter(); if ($a1.BeginAwait($resume)) return; L1: var text = $a1.EndAwait(); var xml = XElement.Parse(text); $builder.SetResult(xml); } catch (Exception $ex) { $builder.SetException($ex); } }; $resume(); return $builder.Task; }
As simple as synchronous code Unifies computational, network and I/O asynchrony More scalable servers More responsive UI
C# 1.0 Managed Code C# 2.0 Generics C# 3.0 Language Integrated Query C# 4.0 Dynamic Typing Asynchronous Programming C# v.Next
Class Field public Foo private string X X Compiler Source code Source File Source code.NET Assembly Meta-programmingRead-Eval-Print Loop Language Object Model DSL Embedding
Visual Studio Async CTP Eric Lippert’s Blog The Async CTP does not currently work if SP1 is installed Need to install on top of the RTM version A new CTP will probably be released soon that will work with SP1