zoukankan      html  css  js  c++  java
  • 04,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");
    }
  • 相关阅读:
    Java线程基础(二)
    Java线程基础(一)
    泛型集合List的详细用法
    Java中日期格式(String、Date、Calendar)的相互转换
    重写Java中包装类的方法
    Java的集合框架(第一次小结)
    node.js 调用mysql 数据库
    win10 系统解决mysql中文乱码问题
    vue-echarts图表
    文件上传的几个例子
  • 原文地址:https://www.cnblogs.com/icuit/p/2799306.html
Copyright © 2011-2022 走看看