zoukankan      html  css  js  c++  java
  • .Net 异步随手记(一)

    今天要记录的内容摘要是:

    什么时候异步代码能“等”在那里,什么时候不会“等”

    这两天Coding的时候碰到一个事儿,就是想让异步等在那里结果却直接执行过去了,比如这样:

     1         async static void Count()
     2         {
     3             Console.WriteLine("Task Void 开始");
     4             Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
     5             int count = 0;
     6             while (count < 10)
     7             {
     8                 Console.WriteLine("Print value:{0}", count);
     9                 count++;
    10                 await Task.Delay(500);
    11             }
    12             Console.WriteLine("Task Void 结束");
    13         }

    接下来写这两句:

    1 var taskVoid = new Task(Count);
    2 await taskVoid;

    哈哈,原本按照其它异步方式去写的时候比如 await HttpClient.GetAsync(); 是非常正常的,程序的逻辑会停在这一句,直到获得结果才会进行下面的语句。但运行 await taskVoid 后,会立即运行下面的语句,这是怎么回事?经过仔细检查发现是因为 Count 方法没有返回值,是 void ,因此必须要加以改造。如果 Count 方法返回值是 Task ,await 才能起效,比如改成这样:

     1         static void Main(string[] args)
     2         {
     3             Entry();
     4             Console.ReadLine();
     5             
     6         }
     7 
     8         async static Task CountAsync()
     9         {
    10             Console.WriteLine("Task Void 开始");
    11             int count = 0;
    12             while (count < 10)
    13             {
    14                 Console.WriteLine("Print value:{0}", count);
    15                 count++;
    16                 await Task.Delay(500);
    17             }
    18             Console.WriteLine("Task Void 结束");
    19         }
    20 
    21         async static void Entry()
    22         {
    23             // 创建一个无参数无返回值的方法
    24             var taskVoid = Task.Factory.StartNew(CountAsync);
    25 
    26             await taskVoid.Result;
    27             // 创建一个 taskVoid 之后才能运行的方法
    28             var taskContinue = taskVoid.ContinueWith(async (t) =>
    29             {
    30 
    31                 Console.WriteLine("这是在 TaskVoid 运行之后才能运行的 TaskContinue,Task void 的状态是 {0}", t.Status);
    32                 await Task.Delay(1000);
    33             });
    34             ;
    35         }
    改造后的异步

    个人理解:

    await 作为语法糖,起作用的对象是 Task ,void 方法返回的不是 Task 自然对之前的写法来讲不起作用。Task 用一个“新线程” 去执行 void 方法,自然立即就“返回”了,但返回并不表示方法结束了,方法内还是按照自己的逻辑去运行了,所以这个时候我只能眼巴巴看着 void 类型的 Count 返回却无力控制它。改成后面的写法之后,改造后的 CountAsync 方法返回的是 Task,意思是告诉上层“我是一个Task”,这个时候 await 就可以起作用了。但直接写 await taskVoid 依旧不能起作用,因为此时 taskVoid 无返回值,也就是立即返回了,所以必须要写成“var taskVoid = Task.Factory.StartNew(CountAsync)” + "await taskVoid.Result"的方式,StartNew 方法会内部新建一个 Task 并返回,这个 Task 的返回值是 CountAsync,而 Result 表示了“我要等待运行 CountAsync 这个异步任务的异步任务的结果返回来”。因此,await 起了作用,执行顺序正确了。

    本人学艺不精,对 .Net 内部基本没什么涉猎,如有老鸟看到希望能提出指正意见,谢谢。

  • 相关阅读:
    GCC 命令行详解 -L 指定库的路径 -l 指定需连接的库名(转载)
    vector,list,deque容器的迭代器简单介绍
    自己动手实现简单的Vector
    浅析STL allocator
    STL中的Traits编程技法
    模板类的全特化、偏特化
    自己动手实现智能指针auto_ptr
    各种排序算法的总结和比较(转)
    (CVE-2017-7269 ) IIS6.0实现远程控制
    (CVE-2016-5195)脏牛本地提权
  • 原文地址:https://www.cnblogs.com/cinlap/p/5761673.html
Copyright © 2011-2022 走看看