04,WP8的async和await
2012-12-09 10:01
393 查看
内容预告:
awaitable的对象如何工作
并行处理的新方法
用async替代BackgroundWorkder
了解为什么不再使用线程和线程池
异步函数与基于任务的编程模型(TPM==Task Programming Model):
WP7.1用.NET4.0的模式支持异步编程:BeginXYZ,EndXYZ函数,如HttpWebRequest.BeginGetResponse, EndGetResponse。
WP7.1异步事件模型:设置一个Completed事件处理器,然后用XYZAsync调用操作,如WebClient.DownloadAsync函数和DownloadCompleted enent。
WP8中任何操作时间可能超过50毫秒的任务都以TPM的方式暴露为一个异步函数。
在WinRT中异步编程很重要,文件IO,网络传输都在用它。
TPM逐渐成为编写异步代码的方式。
WP8中很多新的API都会提供一个基于任务的API。
保证UI的流畅性:比较WP7.1中阻塞式文件IO和WP8中TPM式的文件IO:
WP7.1:
WP8:
上异步代码看起来同步:
编译器做的转换:在一个函数的签名中加上async会使编译器用状态机重新实现这个函数。使用状态机编译器可以在函数扶起和恢复的地方插入一个标记点,而不是阻止线程执行。这些点只会在你显示地用await关键字的时候插入。当你await一个异步操作的时候,以下事情都还没有做:
编译器打包所有当前的调用函数的状态把它们保存在堆上。
函数返回给调用者,允许线程干其他活。
当await标记的操作完成时,函数用保存的状态继续执行。
释放调用线程
:
错误处理:继续向同步代码一样用try..catch就行,当代码异步执行时,在调用的线程上抛出异常:
调用async标记的函数时必须带await吗?当然不,不带await时,调用的函数仍然在后台线程执行,调用线程也不等待结果,async函数返回void或task,而不是Task<TResult>。当你这么做时,智能提示会警告你:
替代BackgroundWorker:如果有长时间执行的代码可以放在后台线程里运行,BackgroundWorkder在WP8仍然支持,并可以取消和报告进度。但这些用Task也能解决。
BackroundWorker:
用Task实现的等效的代码:
BackgroundWorkder的进度汇报:
基于Task的进度汇报:
BackgroundWorker的取消:
基于Task的取消:
awaitable的对象如何工作
并行处理的新方法
用async替代BackgroundWorkder
了解为什么不再使用线程和线程池
异步函数与基于任务的编程模型(TPM==Task Programming Model):
WP7.1用.NET4.0的模式支持异步编程:BeginXYZ,EndXYZ函数,如HttpWebRequest.BeginGetResponse, EndGetResponse。
WP7.1异步事件模型:设置一个Completed事件处理器,然后用XYZAsync调用操作,如WebClient.DownloadAsync函数和DownloadCompleted enent。
WP8中任何操作时间可能超过50毫秒的任务都以TPM的方式暴露为一个异步函数。
在WinRT中异步编程很重要,文件IO,网络传输都在用它。
TPM逐渐成为编写异步代码的方式。
WP8中很多新的API都会提供一个基于任务的API。
保证UI的流畅性:比较WP7.1中阻塞式文件IO和WP8中TPM式的文件IO:
WP7.1:
var isf = IsolatedStorageFile.GetUserStoreForApplication(); using (var fs = new IsolatedStorageFileStream("CaptainsLog.store", FileMode.Open, isf)) { StreamReader reader = new StreamReader(fs); theData = reader.ReadToEnd(); reader.Close(); };
WP8:
StorageFile storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appdata:///local/CaptainsLog.store ")); Stream readStream = await StorageFile.OpenStreamForReadAsync(); using (StreamReader reader = new StreamReader(readStream)) { theData = await reader.ReadToEndAsync(); }
上异步代码看起来同步:
编译器做的转换:在一个函数的签名中加上async会使编译器用状态机重新实现这个函数。使用状态机编译器可以在函数扶起和恢复的地方插入一个标记点,而不是阻止线程执行。这些点只会在你显示地用await关键字的时候插入。当你await一个异步操作的时候,以下事情都还没有做:
编译器打包所有当前的调用函数的状态把它们保存在堆上。
函数返回给调用者,允许线程干其他活。
当await标记的操作完成时,函数用保存的状态继续执行。
释放调用线程
:
错误处理:继续向同步代码一样用try..catch就行,当代码异步执行时,在调用的线程上抛出异常:
private async void SomeMethod() { try { string theData = await LoadFromLocalFolder(); TextBox1.Text = theData; } catch (Exception ex) { // An exception occurred from the async operation } }
调用async标记的函数时必须带await吗?当然不,不带await时,调用的函数仍然在后台线程执行,调用线程也不等待结果,async函数返回void或task,而不是Task<TResult>。当你这么做时,智能提示会警告你:
替代BackgroundWorker:如果有长时间执行的代码可以放在后台线程里运行,BackgroundWorkder在WP8仍然支持,并可以取消和报告进度。但这些用Task也能解决。
BackroundWorker:
private void LaunchTaskButton_Click(object sender, RoutedEventArgs e) { BackgroundWorker bgw = new BackgroundWorker(); bgw.RunWorkerCompleted += ((s, a) =>MessageBox.Show("BackgroundWorker has completed, result: " + (int)a.Result)); bgw.DoWork += ((s, a) =>{ // Simulate some long running work Thread.Sleep(5000); // Return the result a.Result = 1234; }); // Now start execution bgw.RunWorkerAsync(); }
用Task实现的等效的代码:
private async void LaunchTaskButton_Click(object sender, RoutedEventArgs e) { int result = await Task.Factory.StartNew<int>(() =>{ // Simulate some long running work Thread.Sleep(5000); // Return the result return 4321; }); MessageBox.Show("BackgroundWorker has completed, result is: " + result); }
BackgroundWorkder的进度汇报:
BackgroundWorker bgw = new BackgroundWorker(); bgw.WorkerReportsProgress = true; bgw.RunWorkerCompleted += ((s, a) => MessageBox.Show("BackgroundWorker has completed, result: " + (int)a.Result)); bgw.ProgressChanged += ((s, a) => { // Progress Indicator value must be between 0 and 1 SystemTray.GetProgressIndicator(this).Value = (double)a.ProgressPercentage/100.0; }); bgw.DoWork += ((s, a) => { // Simulate some long running work for (int i = 0; i < 10; i++) { Thread.Sleep(500); // Report progress as percentage completed bgw.ReportProgress(i * 10); } a.Result = 1234; // Return the result }); // Now start execution bgw.RunWorkerAsync();
基于Task的进度汇报:
IProgress<int> progressReporter = new Progress<int>((percentComplete) => // Progress Indicator value must be between 0 and 1 SystemTray.GetProgressIndicator(this).Value = (double)percentComplete / 100.0 ); int result = await Task.Factory.StartNew<int>(() => { // Simulate some long running work for (int i = 0; i < 10; i++) { Thread.Sleep(500); // Report progress as percentage completed progressReporter.Report(i * 10); } // Return the result return 4321; } ); MessageBox.Show("BackgroundWorker has completed, result is: " + result);
BackgroundWorker的取消:
BackgroundWorker bgw = new BackgroundWorker(); bgw.WorkerReportsProgress = true; bgw.WorkerSupportsCancellation = true; bgw.RunWorkerCompleted += ((s, a) => { if (a.Cancelled) MessageBox.Show("BackgroundWorker was cancelled"); else MessageBox.Show("BackgroundWorker has completed, result: " + (int)a.Result); } ); bgw.ProgressChanged += ((s, a) => { ... }); bgw.DoWork += ((s, a) =>{ // Simulate some long running work for (int i = 0; i < 10; i++) { Thread.Sleep(500); // Report progress as percentage completed bgw.ReportProgress(i * 10); // Have we been cancelled? bgw.DoWork += ((s, a) => { // Simulate some long running work for (int i = 0; i < 10; i++) { Thread.Sleep(500); // Report progress as percentage completed bgw.ReportProgress(i * 10); // Have we been cancelled? if (bgw.CancellationPending) { a.Cancel = true; return; } } a.Result = 1234; // Return the result }); // Now start execution bgw.RunWorkerAsync();
基于Task的取消:
var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; try { int result = await Task.Factory.StartNew<int>(() => { // Simulate some long running work for (int i = 0; i < 10; i++) { Thread.Sleep(500); // Have we been cancelled? cancellationToken.ThrowIfCancellationRequested(); } return 4321; // Return the result }, cancellationToken); MessageBox.Show("BackgroundWorker has completed, result is: " + result); } catch (OperationCanceledException ex) { MessageBox.Show("Task BackgroundWorker was cancelled"); }
相关文章推荐
- 04,WP8的async和await
- 04,WP8的async和await
- WP8的async和await
- WP8的async和await
- WP8中使用async/await扩展HttpWebRequest
- async与await
- C# Async与Await的使用
- WCF透明代理类,动态调用,支持async/await
- ReactNative踩坑日志——使用async/await语法解决网络请求的异步导致的指令执行顺序错乱问题
- [你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
- C# 异步编程4 async与await 异步程序开发
- async 和 await 的异步处理
- 理解 JavaScript 的 async/await
- decorator, async/await, generator
- .NET 中的 async/await 异步编程
- reactjs 使用异步终级解决方案 async,await实践
- async & await 的前世今生
- async/await使用心得
- ES7 异步函数 (async await)
- ES7-async和await