WP8的async和await

内容预告:

  • 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");
}
复制代码

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值