370 likes | 538 Views
Asynchronous Programming with C# v.Next. Pavel Yosifovich Hi-Tech College pavely@hi-tech.co.il http://blogs.microsoft.co.il/blogs/pavely. Agenda. C# Evolution Trends Synchronous vs. Asynchronous Asynchrony the “old way” The New Way Odds and Ends Summary. C# Evolution. C# 4.0.
E N D
Asynchronous Programming with C# v.Next Pavel Yosifovich Hi-Tech College pavely@hi-tech.co.il http://blogs.microsoft.co.il/blogs/pavely
Agenda • C# Evolution • Trends • Synchronous vs. Asynchronous • Asynchrony the “old way” • The New Way • Odds and Ends • Summary
C# Evolution C# 4.0 Dynamic Typing C# 3.0 Language Integrated Query C# 2.0 Generics C# 1.0 Managed Code
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. JavaScript and Silverlight
C# Evolution C# v.Next Asynchronous Programming C# 4.0 Dynamic Typing C# 3.0 Language Integrated Query C# 2.0 Generics C# 1.0 Managed Code
Responsive UI demo
Asynchrony in a Nutshell • Synchronous Wait for result before returning • string DownloadString(...); • Asynchronous Return now, call back with result • void DownloadStringAsync(..., Action<string> callback); • Asynchronous work != Threads
Synchronous vs. Asynchronous var data = DownloadData(...); ProcessData(data); STOP Thread DownloadData ProcessData DownloadDataAsync(... , data => { ProcessData(data); }); Thread DownloadDataAsync ProcessData
Synchronous vs. Asynchronous var data = DownloadData(...); ProcessData(data); STOP STOP Thread DownloadData ProcessData DownloadDataAsync(... , data => { ProcessData(data); }); Thread DownloadDataAsync ProcessData
Asynchronous Methods • Goal: Just like synchronous programming • Framework: Use Task<T> for all asynchrony • Add Task<T> 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
Task<T> • 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.
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } Message Pump UI Thread
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); }
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); }
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); }
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
Asynchronous Control Flow async voidDoWorkAsync() { var t1 = ProcessFeedAsync("www.acme.com/rss"); var t2 = ProcessFeedAsync("www.xyznews.com/rss"); awaitTask.WhenAll(t1, t2); DisplayMessage("Done"); } asyncTaskProcessFeedAsync(stringurl) { var text = awaitDownloadFeedAsync(url); var doc = ParseFeedIntoDoc(text); awaitSaveDocAsync(doc); ProcessLog.WriteEntry(url); } t1 t2
What About Exceptions? • Should be as simple as the synchronous case varwc = newWebClient(); try { stringtxt = awaitwc.DownloadStringTaskAsync(url); dataTextBox.Text = txt; } catch(WebExceptionx) { // Handle as usual }
How Does it Work? async Task<XElement> GetRssAsync(stringurl) { var client = newWebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; }
How Does it Work? Task<XElement> GetRssAsync(stringurl) { var $builder = AsyncMethodBuilder<XElement>.Create(); var $state = 0; TaskAwaiter<string> $a1; Action $resume = delegate { try { if ($state == 1) goto L1; var client = newWebClient(); 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; } async Task<XElement> GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml; }
Asynchronous Methods • As simple as synchronous code • Unifies computational, network and I/O asynchrony • More scalable servers • More responsive UI
C# Evolution C# v.Next Asynchronous Programming C# 4.0 Dynamic Typing C# 3.0 Language Integrated Query C# 2.0 Generics C# 1.0 Managed Code
Compiler as a Service Meta-programming Read-Eval-Print Loop Class public Foo Language Object Model Field DSL Embedding private X string Compiler Compiler SourceFile .NET Assembly Source code Source code Source code Source code
Resources • Visual Studio Async CTP • http://msdn.com/vstudio/async • Eric Lippert’s Blog • http://blogs.msdn.com/b/ericlippert/ • 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