zoukankan      html  css  js  c++  java
  • Metro Style App 异步简洁而不简单的异步

    Metro Style App 异步-简洁而不简单的异步

    简洁的异步

    在win8 中异步被大大的加强,在code 中占到相当大的比重,按照建议任何耗时超过0.5S的操作都应该使用异步,幸运的是在.NET 4.5中异步的开发相当简单

    (明亮的类库都表示需要异步来操作,可见多么重要)

      

    View Code
    1      private bool test()
    2
    3 {
    4
    5 Method()
    6
    7 return true;
    8
    9 }

     

    这是最原始的方法,当Method() 执行时间过长则会阻塞UI线程 ,在以前我们可能有多种写法来解决,但是在.NET 4.5中 这一切都被大大的简化了

    只要在你需要的地方打上async 和await  关键字即可,async 必须在方法名和返回类型前

    有async 则必须有await ,异步方法的返回类型必须是Task<T> 即 若要返回一个bool类型则方法声明

        

        private async Task<bool> test()

    {

    await Method()

    return true;

    }

     

    在这里要注意的是方法会等待Method 执行完毕后才会返回true, 但是不同的是不会阻塞UI线程 在test()方法内部可以操控UI元素,并且UI 不会假死,你需要注意的是这并不是什么神奇的语法,只是一些语法糖而已,犀利的编译器。

    注意async不能用于 属性,构造函数,

    异步的泥潭

    对于win8 中的异步 在初学阶段我喜欢用泥潭这个词,有可能你会陷入一些奇怪的异步问题,因为在一些情况下 并不总是按照你想象的那样方式运行,可能会死锁 可能会没有等待方法完成就接着往下执行还有很多很多……这里给出几条个人建议

    1. 如果有  void 需要异步执行的方法则把void 换成Task

        

    View Code
     1     public async void btnWrite_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
    2
    3 {
    4
    5 WriteData ();
    6
    7 savedate();
    8
    9 }
    10
    11
    12
    13 private async void WriteData()
    14
    15 {
    16
    17 await Method()
    18
    19 }

     

    我们执行这个btnWrite_Click的异步方法的时候会先进入WriteData() 中 按照上文所说的应该是等待WriteData 执行完毕后才会接着执行  savedate 方法,但是遗憾的是它并不会等待WriteData 执行完毕 就接着执行 savedate了 ,这是因为虽然WriteData 是个异步方法 但是这个异步是针对于 Method(),WriteData  本质是异步方法但是不需要等待 ,但是我们需要一个等待的异步…

    View Code
            public async void btnWrite_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)

    {

    await WriteData ();

    savedate();

    }



    private async Task WriteData()

    {

    await Method()

    }

     

    当我们把void 换成Task 时候 就明确的WriteData 定义为一个需要等待的异步方法 ,这样  btnWrite_Click 就会按照我们设想的那样会等待WriteData 执行完毕 才会执行savedate

     

    1. 用ConfigureAwait(false) 避免死锁

    让我们来完善我们的文件读写,当写入文件失败的时候我们可能要记入log

    public async void btnWrite_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)

    {

    try

    {

    await WriteData();

    btnWrite.Content = "ok";

    }

    catch (Exception)

    {

    WriteLog();

    }

    }

    private async Task WriteData()

    {

    await Method()

    }

    private async Task WriteLog ()

    {

    await Method2()

    }


          

    但是遗憾的是在catch 中我们无法使用await 关键字,既然无法使用await ,那么对于异步方法 我们可以调用  WriteLog().Start() 来开始 ,但是我们无法确保WriteLog()什么时候执行完毕 ,也许在程序关闭了,还在写日志 .这显然不是我们所预期的, 或者我们可以尝试   WriteLog().GetAwaiter();   这个主意不错可是当我们正在运行的时候会发现 程序死锁了,应为在WriteLog().GetAwaiter(); 

    UI线程将会被阻塞 等待WriteLog方法执行完毕,返回控制权,在WriteLog内部会等待Method2()执行完毕 返回控制权.主意Method2 执行在其他线程(来自线程池) ,但是WriteLog则在UI线程执行… UI线程已经被阻塞,死锁就在Method2 执行完毕后发生.幸运的是我们还有办法解决 。

    我们可以在WriteLog().ConfigureAwait(false) MSDN解释如下

     

    • Task.ConfigureAwait(bool continueOnCapturedContext)
      • true (default)
        • Post continuation back to the current context/scheduler
        • false
          • If possible, continue executing where awaited task completes

    个人觉得和Task.Yield();  很相似 .但是Task.Yield();有不确定性 并且需要await 支持。

    Source Address

     

  • 相关阅读:
    奥数视频
    提车应该检查哪?4S店都怕你检查这4个“雷区”,别等后悔才知道
    乒乓球拍子和套胶选择
    2018天津英华国际学校初中报名指南
    水瓶座出生日期是几月几号到几月几号
    乒乓球 世锦赛
    鸡蛋羹要怎么蒸才会更嫩?秘诀在这里
    家庭理财方法:知道这7个定律可以帮你赚更多钱!
    要知道股市有“三底”,估值底、政策底、市场底!
    DbMigration使用方法
  • 原文地址:https://www.cnblogs.com/linlf03/p/2388207.html
Copyright © 2011-2022 走看看