[C#] 走进异步编制程序的社会风气 – 剖析异步方法(上)

三 、How 撤除异步操作

   CancellationToken 和 CancellationTokenSource
那四个类允许你打住执行异步方法。

  (1)CancellationToken
对象涵盖职责是还是不是被裁撤的音信;假诺该对象的习性 IsCancellationRequested

true,任务需终止操作并赶回;该指标操作是不可逆的,且只好动用(修改)贰次,即该指标内的 IsCancellationRequested
属性被安装后,就不能够改变。

  (2)CancellationTokenSource 可制造 CancellationToken
对象,调用 CancellationTokenSource 对象的 Cancel
方法,会使该目的的 CancellationToken 属性 IsCancellationRequested 设置为
true。

  【注意】调用 CancellationTokenSource
对象的 Cancel
方法,并不会执行打消操作,而是会将该目的的 CancellationToken
属性 IsCancellationRequested 设置为 true。

 

  示例

图片 1图片 2

 1     internal class Program
 2     {
 3         private static void Main(string[] args)
 4         {
 5             CancellationTokenSource source = new CancellationTokenSource();
 6             CancellationToken token = source.Token;
 7 
 8             var t = Do.ExecuteAsync(token);
 9 
10             //Thread.Sleep(3000);   //挂起 3 秒
11             //source.Cancel();    //传达取消请求
12 
13             t.Wait(token);  //等待任务执行完成
14             Console.WriteLine($"{nameof(token.IsCancellationRequested)}: {token.IsCancellationRequested}");
15 
16             Console.Read();
17         }
18 
19 
20     }
21 
22     internal class Do
23     {
24         /// <summary>
25         /// 异步执行
26         /// </summary>
27         /// <param name="token"></param>
28         /// <returns></returns>
29         public static async Task ExecuteAsync(CancellationToken token)
30         {
31             if (token.IsCancellationRequested)
32             {
33                 return;
34             }
35 
36             await Task.Run(() => CircleOutput(token), token);
37         }
38 
39         /// <summary>
40         /// 循环输出
41         /// </summary>
42         /// <param name="token"></param>
43         private static void CircleOutput(CancellationToken token)
44         {
45             Console.WriteLine($"{nameof(CircleOutput)} 方法开始调用:");
46 
47             const int num = 5;
48             for (var i = 0; i < num; i++)
49             {
50                 if (token.IsCancellationRequested)  //监控 CancellationToken
51                 {
52                     return;
53                 }
54 
55                 Console.WriteLine($"{i + 1}/{num} 完成");
56                 Thread.Sleep(1000);
57             }
58         }
59     }

View Code

图片 3

图3-1

图片 4

图3-2 注释两行代码

图片 5

图3-3:图3-1和图3-2的履行结果(注释两行代码)

  上海体育场面是不调用 Cancel() 方法的结果图,不会撤废职分的进行。

 

  下图在 3 秒后调用 Cancel() 方法废除任务的施行:

图片 6

图3-4:去掉注释

图片 7

图3-5:图3-1和图3-4的推行结果(去掉注释)

 

  那是上篇《走进异步编制程序的社会风气 – 开端接触 async/await
异步编制程序
》(入门)的第1章内容,首假设与我们一同深切研讨下异步方法。

  本文供给通晓委托的施用。

 

小结

  • 介绍异步方法的语法、三种分裂的归来值类型(void、Task 和
    Task<T>)和控制流程等。
  • 简单易行常用的异步执行措施:Task.Run()。【注意】它是在分化的线程上推行方式。
  • 什么样废除异步操作。

 

一、控制流

     异步方法的协会可拆分成三个不等的区域:

     (1)表明式以前的一部分:从事艺术工作术头到第四个await 表明式之间的具有代码。

     (2)await
表明式:将被异步执行的代码。

     (3)表明式之后的片段:await
表明式的接续部分。

 图片 8

  图1-1

 

  该异步方法执行流程:从await表明式此前的地方伊始,同步执行到第多个await,标识着第2有的举行完结,一般的话此时 await 工作还没形成。当await
职责到位后,该措施将持续联合执行后续部分。在推行的继承部分中,假诺如故留存
await,就再次上述进程。

  当到达 await
表达式时,线程将从异步方法再次回到到调用方法。假如异步方法的归来类型为 Task
或 Task<T>,会创设二个 Task 对象,标识供给异步实现的职分,然后将
Task 重返来调用方法。

 

图片 9

  图1-2

  异步方法的控制流:

  ①异步执行 await 表明式的闲暇任务。

  ②await 表明式执行到位,继续执行后续部分。如再境遇 await
表明式,按相同境况展开始拍录卖。

  ③到达末尾或碰到 return 语句时,依据重回类型能够分二种状态:

    a.void:退出控制流。

    b.Task:设置
Task 的天性并脱离。

    c.Task<T>:设置 Task
的性质和再次回到值(Result 属性)并脱离。

  ④还要,调用方法将继续执行,从异步方法获得 Task
对象。须要值的时候,会停顿等到 Task 对象的 Result
属性被赋值才会继续执行。

 

  【难点】

  ①先是次相遇 await
所重返对象的种类。这么些重返类型正是一起方法头的回来类型,跟 await
表明式的再次回到值没有关系。

  ②到达异步方法的最终或遭逢 return
语句,它并从未当真的归来一个值,而是退出了该情势。

 

二、await 表达式

  await 表明式钦赐了1个异步执行的天职。私下认可景况,该职责在当前线程异步执行。

  每一个任务就是二个 awaitable 类的实例。awaitable 类型指包蕴GetAwaiter() 方法的品种。

  实际上,你并不供给营造和谐的 awaitable,一般只供给利用 Task
类,它正是 awaitable。

  最简便易行的点子是在格局中采用Task.Run() 来创立2个 Task。【注意】它是在差别的线程上推行措施。

 

  让大家一起来看看示例。

图片 10图片 11

 1     internal class Program
 2     {
 3         private static void Main(string[] args)
 4         {
 5             var t = Do.GetGuidAsync();
 6             t.Wait();
 7 
 8             Console.Read();
 9         }
10 
11 
12         private class Do
13         {
14             /// <summary>
15             /// 获取 Guid
16             /// </summary>
17             /// <returns></returns>
18             private static Guid GetGuid()   //与Func<Guid> 兼容
19             {
20                 return Guid.NewGuid();
21             }
22 
23             /// <summary>
24             /// 异步获取 Guid
25             /// </summary>
26             /// <returns></returns>
27             public static async Task GetGuidAsync()
28             {
29                 var myFunc = new Func<Guid>(GetGuid);
30                 var t1 = await Task.Run(myFunc);
31 
32                 var t2 = await Task.Run(new Func<Guid>(GetGuid));
33 
34                 var t3 = await Task.Run(() => GetGuid());
35 
36                 var t4 = await Task.Run(() => Guid.NewGuid());
37 
38                 Console.WriteLine($"t1: {t1}");
39                 Console.WriteLine($"t2: {t2}");
40                 Console.WriteLine($"t3: {t3}");
41                 Console.WriteLine($"t4: {t4}");
42             }
43         }
44     }

View Code

图片 12

图2-1

图片 13

图2-2

   上边 4 个 Task.Run() 都以使用了 Task Run(Func<TReturn> func)
格局来直接或直接调用 Guid.NewGuid()。

 

  Task.Run() 支持 4 中分化的委托项目所代表的措施:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

图片 14图片 15

 1     internal class Program
 2     {
 3         private static void Main(string[] args)
 4         {
 5             var t = Do.GetGuidAsync();
 6             t.Wait();
 7 
 8             Console.Read();
 9         }
10 
11         private class Do
12         {
13             public static async Task GetGuidAsync()
14             {
15                 await Task.Run(() => { Console.WriteLine(Guid.NewGuid()); });   //Action
16 
17                 Console.WriteLine(await Task.Run(() => Guid.NewGuid()));    //Func<TResult>
18 
19                 await Task.Run(() => Task.Run(() => { Console.WriteLine(Guid.NewGuid()); }));   //Func<Task>
20 
21                 Console.WriteLine(await Task.Run(() => Task.Run(() => Guid.NewGuid())));    //Func<Task<TResult>>
22             }
23         }
24     }

View Code

图片 16

图2-3 Task.Run() 方法的重载

 

传送门

  入门:《始发接触 async/await
异步编制程序

  补充篇:《走进异步编制程序的社会风气 –
剖析异步方法(下)

  GUI 篇:《走进异步编制程序的世界 – 在 GUI
中执行异步操作

 


最初的小说链接:http://www.cnblogs.com/liqingwen/p/5844095.html

 【参考】《Illustrated C# 2012》

介绍异步方法

     异步方法:在实行到位前及时赶回调用方法,在调用方法继续执行的进度中完结职责。

     语法分析:

     (1)关键字:方法头使用 async
修饰。

     (2)供给:包涵N(N>0) 个 await 表明式(不设有 await 表达式的话 IDE
会发出警示),表示需求异步执行的职分。【备注】多谢 czcz1024 的考订与增加补充:没有的话,就和一般性方法同样进行了。

     (3)再次来到类型:只可以回到 3
种档次(void、Task 和 Task<T>)。Task 和 Task<T>
标识重回的靶子会在后天到位工作,表示调用方法和异步方法能够继续执行。

     (4)参数:数量不限。但不能够利用 out
和 ref 关键字。

     (5)命名约定:方法后缀名应以 Async
结尾。

     (6)别的:匿名方式和 拉姆da
表达式也足以当作异步对象;async 是一个上下文关键字;关键字 async
必须在回去类型前。

 

图片 17图1
异步方法的简练结构图

  关于 async 关键字:

  ①在回到类型从前包含 async 关键字

  ②它只是标识该措施包括1个或八个 await
表明式,即,它自个儿不成立异步操作。

  ③它是上下文关键字,即可作为变量名。

 

  今后先来不难解析一下那两种回到值类型:void、Task 和 Task<T>

  (1)Task<T>:调用方法要从调用中获取1个T 类型的值,异步方法的回到类型就亟须是Task<T>。调用方法从 Task 的
Result 属性获取的正是 T 类型的值。

图片 18图片 19

 1         private static void Main(string[] args)
 2         {
 3             Task<int> t = Calculator.AddAsync(1, 2);
 4 
 5             //一直在干活
 6 
 7             Console.WriteLine($"result: {t.Result}");
 8 
 9             Console.Read();
10         }

Program.cs

图片 20图片 21

 1     internal class Calculator
 2     {
 3         private static int Add(int n, int m)
 4         {
 5             return n + m;
 6         }
 7 
 8         public static async Task<int> AddAsync(int n, int m)
 9         {
10             int val = await Task.Run(() => Add(n, m));
11 
12             return val;
13         }
14     }

View Code 

图片 22

图2

图片 23

图3

 

  (2)Task:调用方法不须求从异步方法中取重回值,不过希望检查异步方法的景色,那么能够选拔能够回来
Task 类型的靶子。可是,即便异步方法中含有 return
语句,也不会回到任杨晓伟西。

图片 24图片 25

 1         private static void Main(string[] args)
 2         {
 3             Task t = Calculator.AddAsync(1, 2);
 4 
 5             //一直在干活
 6 
 7             t.Wait();
 8             Console.WriteLine("AddAsync 方法执行完成");
 9 
10             Console.Read();
11         }

Program.cs

图片 26图片 27

 1     internal class Calculator
 2     {
 3         private static int Add(int n, int m)
 4         {
 5             return n + m;
 6         }
 7 
 8         public static async Task AddAsync(int n, int m)
 9         {
10             int val = await Task.Run(() => Add(n, m));
11             Console.WriteLine($"Result: {val}");
12         }
13     }

View Code

 

图片 28

 

图4

图片 29

图5

     

  (3)void:调用方法执行异步方法,但又不需求做进一步的并行。 

图片 30图片 31

 1         private static void Main(string[] args)
 2         {
 3             Calculator.AddAsync(1, 2);
 4 
 5             //一直在干活
 6 
 7             Thread.Sleep(1000); //挂起1秒钟
 8             Console.WriteLine("AddAsync 方法执行完成");
 9 
10             Console.Read();
11         }

Program.cs

图片 32图片 33

 1     internal class Calculator
 2     {
 3         private static int Add(int n, int m)
 4         {
 5             return n + m;
 6         }
 7 
 8         public static async void AddAsync(int n, int m)
 9         {
10             int val = await Task.Run(() => Add(n, m));
11             Console.WriteLine($"Result: {val}");
12         }
13     }

Calculator.cs

图片 34

图6

图片 35

图7

 

走进异步编制程序的世界 – 剖析异步方法(上)

目录

 

相关文章