走进异步编程的世界,异步编制程序

By admin in 4858.com on 2019年4月3日

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

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

一、简介

[C#] 异步编制程序,

  那是上篇《走进异步编制程序的世界 – 初始接触 async/await
异步编制程序》(入门)的第二章内容,主要是与大家共同深切斟酌下异步方法。

  本文供给明白委托的接纳。

 

  那是上篇《走进异步编制程序的社会风气 – 初叶接触 async/await
异步编制程序》(入门)的第3章内容,首要是与我们壹起深远研究下异步方法。

  本文供给驾驭委托的行使。

 

  首先来看看.net的前进中的种种阶段的特点:NET 与C#
的每个版本公布都是有二个“主题”。即:C#①.0托管代码→C#2.0泛型→C#3.0LINQ→C#四.0动态语言→C#4.5异步编程

剖析异步方法

目录

  • 介绍异步方法

  • 控制流

  • await
    表达式

  • How
    撤消异步操作

 

目录

  • 介绍异步方法

  • 控制流

  • await
    表达式

  • How
    撤消异步操作

 

 

  那是上篇《先河接触 async/await
异步编制程序》(入门)的第3章内容,主借使深远摸底异步方法,建议大家先看入门篇,不够长。

  本文供给理解委托的使用。

 

介绍异步方法

     异步方法:在举行到位前及时回去调用方法,在调用方法继续执行的历程中成功职分。

     语法分析:

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

     (贰)要求:包涵N(N>0) 个 await 表达式(不存在 await 表明式的话 IDE
会发出警告),表示要求异步执行的天职。【备注】谢谢 czcz1024 的改正与互补:未有的话,就和平凡方法同样进行了。

     (3)重临类型:只可以回去 三种档次(void、Task 和 Task<T>)。Task 和 Task<T>
标识重返的目的会在以往到位工作,表示调用方法和异步方法能够继续执行。

     (四)参数:数量不限。但无法利用 out
和 ref 关键字。

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

     (六)其余:匿名情势和 拉姆da
表明式也得以当作异步对象;async 是2个上下文关键字;关键字 async
必须在回去类型前。

 

4858.com 1图壹异步方法的简易结构图

  关于 async 关键字:

  一在回到类型此前包蕴 async 关键字

  贰它只是标识该格局包蕴一个或四个 await
表明式,即,它自个儿不创立异步操作。

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

 

  以往先来不难分析一下这二种回到值类型:void、Task 和 Task<T>

  (一)Task<T>:调用方法要从调用中获取贰个T 类型的值,异步方法的回来类型就不能够不是Task<T>。调用方法从 Task 的
Result 属性获取的正是 T 类型的值。

4858.com 24858.com 3

 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

4858.com 44858.com 5

 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 

4858.com 6

图2

4858.com 7

图3

 

  (二)Task:调用方法不要求从异步方法中取重返值,但是希望检查异步方法的图景,那么能够选用能够回去
Task 类型的指标。可是,就算异步方法中蕴藏 return
语句,也不会再次回到任何事物。

4858.com 84858.com 9

 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

4858.com 104858.com 11

 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

 

4858.com 12

 

图4

4858.com 13

图5

     

  (三)void:调用方法执行异步方法,但又不必要做进一步的互相。 

4858.com 144858.com 15

 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

4858.com 164858.com 17

 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

4858.com 18

图6

4858.com 19

图7

 

介绍异步方法

     异步方法:在实施到位前及时赶回调用方法,在调用方法继续执行的进程中做到职分。

     语法分析:

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

     (二)供给:包涵N(N>0) 个 await 表明式(不设有 await 表明式的话 IDE
会发出警示),表示须要异步执行的天职。【备注】多谢 czcz1024 的改正与补偿:未有的话,就和一般性方法同样进行了。

     (叁)再次来到类型:只好回到 三连串型(void、Task 和 Task<T>)。Task 和 Task<T>
标识重临的对象会在以往实现工作,表示调用方法和异步方法能够继续执行。

     (四)参数:数量不限。但不可能采纳 out
和 ref 关键字。

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

     (陆)其它:匿名情势和 拉姆da
表达式也得以作为异步对象;async 是2个上下文关键字;关键字 async
必须在回到类型前。

 

4858.com 20图壹 异步方法的简便结构图

  关于 async 关键字:

  壹在再次来到类型以前包罗 async 关键字

  2它只是标识该方法包涵3个或多少个 await
表达式,即,它本身不成立异步操作。

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

 

  现在先来简单解析一下那二种回到值类型:void、Task 和 Task<T>

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

4858.com 214858.com 22

 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

4858.com 234858.com 24

 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 

4858.com 25

图2

4858.com 26

图3

 

  (二)Task:调用方法不要求从异步方法中取再次回到值,不过希望检查异步方法的气象,那么能够接纳能够重返Task 类型的靶子。但是,固然异步方法中隐含 return
语句,也不会回来任周永才西。

4858.com 274858.com 28

 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

4858.com 294858.com 30

 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

 

4858.com 31

 

图4

4858.com 32

图5

     

  (三)void:调用方法执行异步方法,但又不须要做进一步的互动。 

4858.com 334858.com 34

 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

4858.com 354858.com 36

 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

4858.com 37

图6

4858.com 38

图7

 

  下边作者来归纳的介绍一下异步编制程序:异步编制程序,在 .NET Framework 四.5 和
Windows 运转时采纳异步帮助。
编写翻译器可进行开发人士曾开始展览的高难度工作,且应用程序保留了多少个像样于同台代码的逻辑结构。
由此,你只需做一小部分工作就能够获取异步编制程序的保有好处。 

目录

 

一、控制流

     异步方法的构造可拆分成多个分歧的区域:

     (壹)表明式以前的1部分:从点子头到第一个await 表达式之间的装有代码。

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

     (三)表明式之后的片段:await
表明式的继承部分。

 4858.com 39

  图1-1

 

  该异步方法执行流程:从await表明式在此以前的地点初叶,同步实施到第一个await,标识着第壹片段实行实现,1般的话此时 await 工作还没完结。当await
任务成功后,该办法将连续联合实施后续部分。在执行的后续部分中,借使照旧存在
await,就再次上述进度。

  当到达 await
表明式时,线程将从异步方法重返到调用方法。要是异步方法的回到类型为 Task
或 Task<T>,会创建三个 Task 对象,标识要求异步实现的天职,然后将
Task 重回来调用方法。

 

4858.com 40

4858.com ,  图1-2

  异步方法的控制流:

  1异步执行 await 表明式的闲暇职责。

  贰await 表达式执行到位,继续执行后续部分。如再相见 await
表明式,按相同情形开始展览拍卖。

  三到达末尾或碰着 return 语句时,依照重返类型能够分三种情形:

    a.void:退出控制流。

    b.Task:设置
Task 的性质并退出。

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

  肆而且,调用方法将继续执行,从异步方法得到 Task
对象。须求值的时候,会废不过返等到 Task 对象的 Result
属性被赋值才会继续执行。

 

  【难点】

  壹先是次蒙受 await
所重返对象的品类。那些重临类型正是壹块方法头的归来类型,跟 await
表明式的再次来到值未有涉及。

  二到达异步方法的最后或遇到 return
语句,它并从未真的的回到三个值,而是退出了该方式。

 

一、控制流

     异步方法的组织可拆分成八个区别的区域:

     (一)表明式从前的1部分:从章程头到第贰个await 表明式之间的装有代码。

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

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

 4858.com 41

  图1-1

走进异步编程的世界,异步编制程序。 

  该异步方法执行流程:从await表明式之前的地方开头,同步实施到第二个await,标识着第三某个进行完结,一般的话此时 await 工作还没到位。当await
任务成功后,该措施将继承联合实施后续部分。在执行的后续部分中,若是照旧存在
await,就再次上述进程。

  当到达 await
表明式时,线程将从异步方法再次来到到调用方法。假如异步方法的回到类型为 Task
或 Task<T>,会创设3个 Task 对象,标识必要异步达成的天职,然后将
Task 重临来调用方法。

 

4858.com 42

  图1-2

  异步方法的控制流:

  1异步执行 await 表达式的闲暇任务。

  二await 表明式执行到位,继续执行后续部分。如再相见 await
表达式,按相同情状展开处理。

  三到达末尾或蒙受 return 语句时,依据再次回到类型能够分三种状态:

    a.void:退出控制流。

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

    c.Task<T>:设置 Task
的习性和再次来到值(Result 属性)并退出。

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

 

  【难点】

  一首先次相遇 await
所再次来到对象的类型。那一个重返类型就是二只方法头的回来类型,跟 await
表达式的重临值未有涉嫌。

  贰到达异步方法的终极或碰到 return
语句,它并未当真的归来四个值,而是退出了该方法。

 

 

介绍异步方法

   
 异步方法:在实践到位前及时赶回调用方法,在调用方法继续执行的经过中完毕任务。
     语法分析:      (一)关键字:方法头使用 async 修饰。    
 (二)须要:包涵 N(N>0) 个 await 表明式(不存在 await 表明式的话
IDE
会发出警示),表示必要异步执行的职责。【备注】感激 czcz10贰四 的考订与增加补充:未有的话,就和平凡方法一致实行了。
     (三)重临类型:只可以回到 3 种档次(void、Task 和
Task<T>)。Task 和 Task<T>
标识重临的靶子会在今日形成工作,表示调用方法和异步方法能够继续执行。    
 (4)参数:数量不限。但不能够使用 out 和 ref 关键字。    
 (5)命名约定:方法后缀名应以 Async 结尾。      (陆)其余:匿名方式和
拉姆da 表明式也得以用作异步对象;async 是一个上下文关键字;关键字 async
必须在再次来到类型前。     关于 async 关键字:

  1在回去类型在此以前包罗 async 关键字

  贰它只是标识该措施包蕴二个或多少个 await
表明式,即,它自己不创立异步操作。

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

 

  以后先来根本分析一下那二种回到值类型:void、Task 和 Task<T>

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

4858.com 43 1 private
static void Main(string[] args) 2 { 3 Task<int> t =
Calculator.AddAsync(一, 2); 四 5 //一直在办事 陆 柒Console.WriteLine($”result: {t.Result}”); 八 玖 Console.Read(); 十 } Program.cs
4858.com 44 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 

 

  (二)Task:调用方法不需求从异步方法中取再次来到值,不过希望检查异步方法的动静,那么能够选拔可以回来
Task 类型的靶子。不过,固然异步方法中含有 return
语句,也不会回去任何事物。

4858.com 45 1 private
static void Main(string[] args) 二 { 3 Task t = Calculator.AddAsync(一,
2); 四 伍 //平素在劳作 陆 七 t.Wait(); 八 Console.WriteLine(“AddAsync
方法执行到位”); 九 十 Console.Read(); 1一 } Program.cs
4858.com 46 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

4858.com 47

图4

4858.com 48

图5

     

  (3)void:调用方法执行异步方法,但又不供给做越来越的竞相。 

4858.com 49 1 private
static void Main(string[] args) 二 { 3 Calculator.AddAsync(一, 贰); 四 5
//一向在工作 陆 七 Thread.Sleep(一千); //挂起一分钟 八Console.WriteLine(“AddAsync 方法执行到位”); 玖 十 Console.Read(); 1一 }
Program.cs
4858.com 50 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

4858.com 51

图6

4858.com 52

图7

 

二、await 表达式

  await 表明式钦赐了一个异步执行的天职。默许情状,该职责在脚下线程异步执行。

  每三个任务便是2个 awaitable 类的实例。awaitable 类型指包罗GetAwaiter() 方法的花色。

  实际上,你并不供给创设筑组织调的 awaitable,一般只须要动用 Task
类,它就是 awaitable。

  最简易的方法是在章程中应用
Task.Run() 来创建3个 Task。【注意】它是在分化的线程上执行方式。

 

  让大家1并来看望示例。

4858.com 534858.com 54

 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

4858.com 55

图2-1

4858.com 56

图2-2

   下边 四 个 Task.Run() 都是采取了 Task Run(Func<TReturn> func)
格局来间接或直接调用 Guid.NewGuid()。

 

  Task.Run() 援救 四 中区别的寄托项目所代表的主意:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

4858.com 574858.com 58

 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

4858.com 59

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

 

二、await 表达式

  await 表达式钦定了贰个异步执行的天职。默许景况,该职责在最近线程异步执行。

  每三个职责正是三个 awaitable 类的实例。awaitable 类型指包罗GetAwaiter() 方法的品种。

  实际上,你并不要求营造和谐的 awaitable,一般只须求动用 Task
类,它就是 awaitable。

  最简易的点子是在措施中央银行使
Task.Run() 来创制三个 Task。【注意】它是在不一致的线程上实施方式。

 

  让大家1同来看望示例。

4858.com 604858.com 61

 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

4858.com 62

图2-1

4858.com 63

图2-2

   上面 4 个 Task.Run() 都以运用了 Task Run(Func<TReturn> func)
方式来直接或直接调用 Guid.NewGuid()。

 

  Task.Run() 扶助 4 中不相同的信托项目所代表的措施:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

4858.com 644858.com 65

 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

4858.com 66

图二-叁 Task.Run() 方法的重载

 

  所谓的异步编制程序是行使CPU空闲时间和多核的表征,它所再次来到的Task或Task<TResult>是对await的一个答应,当职务履行达成后回到三个结出给接收者。那里看看那几个大概各位不太驾驭,不妨,下边会有教书。

一、控制流

     异步方法的布局可拆分成八个不等的区域:    
 (壹)表明式以前的部分:从事艺术工作术头到第贰个 await 表明式之间的有着代码。  
   (二)await 表达式:将被异步执行的代码。    
 (三)表明式之后的局地:await 表明式的继续部分。   1 internal class
Program 二 { 3 private static void Main(string[] args) 4 { 五 var t =
Do.GetGuidAsync(); 陆 t.Wait(); 柒 八 Console.Read(); 玖 } 10 1一 1二 private
class Do 壹3 { 1四 /// <summary> 一伍 /// 获取 Guid 1六 ///
</summary> 1七 /// <returns></returns> 1八 private
static Guid GetGuid() //与Func<Guid> 包容 19 { 20 return
Guid.NewGuid(); 二一 } 2贰 二三 /// <summary> 二四 /// 异步获取 Guid 25
/// </summary> 二陆 /// <returns></returns> 2七 public
static async Task GetGuidAsync() 2八 { 29 var myFunc = new
Func<Guid>(GetGuid); 30 var t一 = await Task.Run(myFunc); 31 3二 var
t二 = await Task.Run(new Func<Guid>(GetGuid)); 3三 3四 var t三 = await
Task.Run(() => GetGuid()); 3五 36 var t四 = await Task.Run(() =>
Guid.NewGuid()); 叁七 3八 Console.WriteLine($”t一: {t1}”); 3九Console.WriteLine($”t二: {t2}”); 40 Console.WriteLine($”t三: {t叁}”); 四一Console.WriteLine($”t肆: {t四}”); 4贰 } 肆三 } 4四 } View Code

图2-1

图2-2

   上面 四 个 Task.Run() 都是采纳了 Task Run(Func<TReturn> func)
格局。

 

  Task.Run() 补助 四中差异的寄托项目所代表的不贰秘诀:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

4858.com 67 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

 

三、How 撤销异步操作

   CancellationToken 和 CancellationTokenSource
那八个类允许你结束执行异步方法。

  (一)CancellationToken
对象涵盖职分是不是被撤回的消息;假使该对象的属性 IsCancellationRequested

true,职务需终止操作并重返;该对象操作是不可逆的,且只好选取(修改)3遍,即该目的内的 IsCancellationRequested
属性被安装后,就无法改变。

  (二)CancellationTokenSource 可创建 CancellationToken
对象,调用 CancellationTokenSource 对象的 Cancel
方法,会使该指标的 CancellationToken 属性 IsCancellationRequested 设置为
true。

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

 

  示例

4858.com 684858.com 69

 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

4858.com 70

图3-1

4858.com 71

图三-二 注释两行代码

4858.com 72

图叁-三:图3-一和图3-2的实行理并了结果(注释两行代码)

  上海教室是不调用 Cancel() 方法的结果图,不会吊销任务的实施。

 

  下图在 3 秒后调用 Cancel() 方法撤除职分的履行:

4858.com 73

图三-肆:去掉注释

4858.com 74

图三-五:图3-一和图三-四的实践结果(去掉注释)

 

3、How 废除异步操作

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

  (1)CancellationToken
对象涵盖任务是还是不是被注销的音信;假若该对象的质量 IsCancellationRequested

true,职责需终止操作并赶回;该对象操作是不可逆的,且只可以利用(修改)一次,即该指标内的 IsCancellationRequested
属性被装置后,就不能够改变。

  (二)CancellationTokenSource 可创设 CancellationToken
对象,调用 CancellationTokenSource 对象的 Cancel
方法,会使该指标的 CancellationToken 属性 IsCancellationRequested 设置为
true。

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

 

  示例

4858.com 754858.com 76

 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

4858.com 77

图3-1

4858.com 78

图三-二 注释两行代码

4858.com 79

图3-叁:图叁-一和图3-二的执行结果(注释两行代码)

  上海体育场合是不调用 Cancel() 方法的结果图,不会收回职务的推行。

 

  下图在 三 秒后调用 Cancel() 方法撤除职务的实施:

4858.com 80

图三-四:去掉注释

4858.com 81

图三-伍:图三-一和图三-四的履行结果(去掉注释)

 

 

三、撤销异步操作

 

小结

  • 介绍异步方法的语法、两种差别的归来值类型(void、Task 和
    Task<T>)和控制流程等。
  • 简短常用的异步执行格局:Task.Run()。【注意】它是在分化的线程上实施办法。
  • 怎么撤除异步操作。

 

小结

  • 介绍异步方法的语法、三种不一样的归来值类型(void、Task 和
    Task<T>)和控制流程等。
  • 粗略常用的异步执行格局:Task.Run()。【注意】它是在差别的线程上实施办法。
  • 何以裁撤异步操作。

 

二、使用表达

肆、十分处理

 

传送门

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

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

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

 


初稿链接:

 【参考】《Illustrated C# 2012》

传送门

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

  补充篇:《走进异步编制程序的世界 –
剖析异步方法(下)》

  GUI 篇:《走进异步编程的世界 – 在 GUI
中实践异步操作》

 


初稿链接:

 【参考】《Illustrated C# 2012》

艺术签名包括一个 Async 或 async 修饰符。

五、在调用方法中1起地伺机任务

 

 

陆、在异步方法中异步地守候职务

 

遵从预约,异步方法的名目以“Async”后缀结尾。

七、Task.Delay 方法

 

 

小结

 

归来类型为下列项目之壹:

传送门

  入门:《初阶接触 async/await 异步编程》

 


 

–那是预览版本,最后整理完核对后将放上首页,不便之处请见谅–

] 异步编制程序, 剖析异步方法 序
那是上篇《开端接触 async/await
异步编制程序》(入门)的第三章内容,主如若深深精通异步方法,建议我们先…

 

万1您的法子有操作数为 TResult 类型的回来语句,则为
Task<TResult>。

 

只要你的法门未有回到语句或有所未有操作数的归来语句,则为 Task。

 

设若您编写的是异步事件处理程序,则为 Void(Visual Basic 中为 Sub)。

 

关于详细新闻,请参见本核心后边的“再次回到类型和参数”。

 

方法壹般包罗至少二个 await
表达式,该表明式标记3个点,在该点上,直到等待的异步操作达成章程才能三番五次。
同时,将艺术挂起,并且控件重返到方式的调用方。(那里所谓的挂起正是上文所涉嫌的允诺,异步方法承诺会给调用方八个结出)

 

三、示例

  实践才是查看真理的极品途径。

 

 

using System;

using System.Diagnostics;

using System.Net.Http;

using System.Threading.Tasks;

 

namespace 异步递归

{

    class Program

    {

        static void Main(string[] args)

        {

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            ConsoleAsync1();

            stopwatch.Stop();

            Console.WriteLine(“同步方法用时:” +
stopwatch.ElapsedMilliseconds);

            stopwatch.Reset();

            stopwatch.Start();

            ConsoleAsync();

            stopwatch.Stop();

            Console.WriteLine(“异步方法用时:”+
stopwatch.ElapsedMilliseconds);

 

            Console.Read();

        }

 

        private static async void ConsoleAsync()

        {

            Console.WriteLine(“异步方法开首”);

            Console.WriteLine(“Result:” + await SumAsync(10));

            Console.WriteLine(“异步方法甘休”);

        }

        private static async Task<int> SumAsync(int part)

        {

            if ((part += 10) >= 100)

            {

                return 100;

            }

            HttpClient client = new HttpClient();

            Task<string> getStringTask =
client.GetStringAsync(“”);

            Console.WriteLine(DateTime.Now.Millisecond + ” 异步 ” +
(await getStringTask).Length);

            return await SumAsync(part);

        }

 

        private static void ConsoleAsync1()

        {

            Console.WriteLine(“同步方法初阶”);

            Console.WriteLine(“Result:” + SumAsync1(10));

            Console.WriteLine(“同步方法截止”);

        }

 

        private static int SumAsync1(int part)

        {

            if ((part += 10) >= 100)

            {

                return 100;

            }

            HttpClient client = new HttpClient();

            Task<string> getStringTask =
client.GetStringAsync(“”);

            Console.WriteLine(DateTime.Now.Millisecond + ” 同步 ” +
getStringTask.Result.Length);

            return SumAsync1(part);

        }

    }

}

 

  示例介绍:

 

    一、那几个事例中有二种完毕情势:(一)利用异步编制程序的艺术完结(二)利用日常同步格局贯彻

 

    二、同时这些事例中达成了递归,那个能够绝不思索,博主只是想证美赞臣(Meadjohnson)下在异步的情形下,递归是不是有效而已,实验结果为可行。

 

    叁、那段代码中的GetStringAsync()方法是获取远程界面内容用的,主要指标是延伸响应时间。

 

  在行使10二线程编写端口扫描程序时,我要好深感同步和分明全体线程都推行完的小运是3个相比较费心的难题。有园友评论说今后曾经不手动成立thread对象了,而是间接行使Task异步格局,我的网络编制程序老师也讲到了异步编制程序的优越性。在学习了课本上的知识后,进行了3个计算分享给我们。从.NET四.5发端,用async和await关键字再添加Task.Run是3个那多少个不错的异步编制程序模型。

1.await和async

  异步格局从技术上看便是选拔委托来兑现的,它的主要利益是在异步执行的经过中,用户依然能够操控UI界面。使用Task类和利用Thread类有诸多1般的地点,Task类也是因而调用方法去贯彻1个职务的做到,方法不过是命超级模特式或匿名方式,在实践进度中可利用async和await来贯彻异步执行。async是四个修饰符,它不得不用在艺术照有趣的事件处理程序的签订契约中。对于措施可分为有重临值和无再次回到值二种情形,事件则唯有一种,如上面三条语句所示:

    private async Task<int> MethodAsync();//有重返值的异步方法

    private async Task MethodAsync();//无再次来到值的异步方法

    private async void btnOk_Click();//异步事件处理程序

  await是一个运算符,它代表等待异步执行的结果。也能够精晓为await运算符实际上是对章程的重回值实行操作,也正是对Task<Result>进行操作,而不是对艺术自己进行操作。还有少数要小心,await是毫无疑问要放在异步方法的个中,假设未有放在里面包车型客车话,VS会自动报错。以下是async和await使用的例子: 

    private async void button5_Click(object sender, EventArgs e)
    {
      Task a = Method1Async();
      //此处可继续执行别的代码
      await a;//等待任务a达成
      Task<int> b = Method2Async();
      //此处可继续执行别的代码
      int c = await b;//等待职责b达成,且能够得到职分b的重返值
    }

    Task Method1Async();
    async Task<int> Method2Async()
    {
      await Task.Delay(100);
      return 1;
    }

  await和协同编制程序最大的分化之处是:异步等待任务到位的时候,在不会继续执行前面包车型大巴代码时,也不会影响界面包车型大巴操作。在.NET提供的类中,异步方法都以预订用Async作为后缀,那样可以很明白的明亮这一个艺术是异步方法照旧三只方法。

二. 开立职分

  创立任务相当于将义务与要实施的方法联系起来,编写职务执行的法未时,这几个法子既能够是联合方法也能够是异步方法,还足以是匿名情势。执行异步方法时,必须用async和Task共同表示并未有重回值的职务,用async和Task<TResult>共同表示再次来到值为TResult的天职。以下是概念执行职分的章程。

    private async void button5_Click(object sender, EventArgs e)
    {

      //Task.Run方法表示使用暗中认可的职责调度程序在线程池中经过后台执行钦点的职分

      //如若不供给协调去调度措施,使用那几个格局最利于
      await Task.Run(()=>Method一Async());//执行壹起方法
      int c = await
Task.Run(()=>Method二Async());//执行异步方法
      await Task.Run(async () => { c = 贰;
});//执行异步匿名格局
    }
    void Method1Async();
    async Task<int> Method2Async(){…}

  Task.Run方法常用的重载格局有以下四种,其它它也是能够用new关键字显得创建职务,然则那种办法用的不多。

    Task Run(Func<Task> function);//执行不带重返值的职务

    Task<TResult>
Run<TResult>(Func<Task<TResult>>
function);//执行带重返值的职分

    Task<TResult> Run<TResult>(Func<Task<TResult>>
function, CancellationToken
cancellationToken);//执行进度中得以监听撤销布告

    Task Run(Func<Task> function, CancellationToken
cancellationToken);//执行进度中能够监听撤消文告

3. 甘休任务

  在实施职务时肯定会并发须求截止职务的气象,那里的平息告诉职责你要尽快停下来不再举办了,而不是向来接销售毁职责实例。那里能够打个要是,学生1起出去吃饭了,学生与先生都在班群里面,突然班群里老师说要让同学们汇集,倘使全部同学都看到那些消息,然后学生们伊始起身,那样就足以正确的成团。下边包车型客车例子有二个很要紧的前提,那正是有着同学都要探望这一个音讯,相当于学员是随时监听新闻的。CancellationTokenSource类和CancellationToken结构用于落到实处四线程、线程池和Task职分的吊销操作,处理方式与地点的事例相似。创设的班群正是CancellationTokenSource对象,收到的关照正是CancellationToken对象。CancellationTokenSource用于创设撤废布告,CancellationToken则用于传播应撤销操作的通报,当调用职务前,可以先创造裁撤源对象CancellationTokenSource
cts=new CancellationTokenSource();,借使希望在30秒后自行发出撤废布告,能够流传参数CancellationTokenSource(TimeSpan.FromSeconds(30));CancellationToken
ct=cts.Token;,后一句代码是获得撤消的通报。CancellationTokenSource还有三个Cancel方法,将那本性子设为true时,该方法会将全体添加了撤回标记的CancellationToken对象的IsCancellationRequested属性都安装为true,那样废除文告就传递到了正在实践的职务。

  义务收到撤除公告后,能够选拔三种办法来终止操作。第2种办法是不难的从委托再次回到。那种完毕方式接近于在调用职务的代码中四个bool值来表示撤废文告,职责收到后就直接回到了。当使用这种方式时职务情况的重回值为TaskStatus.RanToCompletion枚举值,它意味着符合规律达成,而不是TaskStatus.Canceled枚举值。第两种方法是在代码里吸引OperationCanceledException卓殊,并将其传递到在其上呼吁了注销的标记,选择那种艺术收回的职责会转移为用Canceled枚举值表示的景况。完毕引发这几个的首要采纳办法是调用ct.ThrowIfCancellationRequestes();。以下是代码示例,写了二个winform程序,利用进度条来撤除职责。第三个图是不曾抓住那个时,程序退出for循环,执行前面包车型客车代码后回来了,第2张图是第二种方法,引发了老大后一向跳转到catch语句块了。

4858.com 82

4858.com 83

4858.com 84

     CancellationTokenSource cts;
        private async void button3_Click(object sender, EventArgs e)
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            cts = new CancellationTokenSource();
            var aa = MYThreadAsync("a", cts.Token);
            try
            {
                await aa;
                listBox1.Items.Add("await后面");
            }
            catch
            {
                if (aa.IsCanceled)
                    listBox1.Items.Add("a取消");
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }

        public async Task MYThreadAsync(string s, CancellationToken ct)
        {
            for (int i = 0; i < 50; i++)
            {
                if (ct.IsCancellationRequested)
                    break;          //点击关闭按钮,IsCancellationRequested就为true,就会退出for循环,这是第一种方式
                progressBar1.Value += 2;
                await Task.Delay(100);
                ct.ThrowIfCancellationRequested();//这是第二种方式,它会终止任务并且返回catch语句块里面
            }
            listBox1.Items.Add("任务" + s + "完成了");
        }

4858.com 85

四. 赢得任务执行的状态

  在异步编程中,很强烈任务执行的景观是贰个不行重大的参数。在任务的生命周期里,能够因而Status属性来收获任务履行的情状,当职责达成后还足以经过义务属性知道职责成功的意况。可利用义务实例的Status属性获取职责履行的情事,职务执行的情事用TaskStatus枚举表示,以下是TaskStatus的枚举值:

Created:职务现已开端化,但尚未进入调度布署

WaitingForActivation:该职分已跻身调度布署,正在等待被调度程序激活

WaitingToRun:该任务已被调度程序激活,但未曾起头推行

Running:该职务正在运作,但从未到位

RanToCompletion:该职务现已打响做到

Canceled:该义务由于被撤回而达成,引发那么些或调用方已向该职责的CancellationToken发出能量信号

Faulted:该职责因为出现未经处理的很是而做到

WaitingForChildrenToComplete:该任务自作者已成功,正等待附加的子职责到位

  职责完结情状城门失火的本性有IsCompleted、IsCanceled和IsFaulted等属性,从单词意思上看简单精通它们的趣味,当中要专注IsCompleted属性表示职责是不是做到,无论是符合规律结束依然因为废除或越发而做到都为成功。

5. 职务履行的进程

  有时候大家盼望让某个异步操作提供进程通报,以便在界面中体现异步操作实践的速度,可以用Progress<T>类来得到职分履行的快慢。以下是采纳格局里的Report方法将艺术内变量的值传回成立职责的事件代码里,从而立异进度条的值。

4858.com 86

     CancellationTokenSource cts;
        private async void button3_Click(object sender, EventArgs e)
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            cts = new CancellationTokenSource();
            CancellationToken ct = cts.Token;
            var pp = new Progress<int>();
            pp.ProgressChanged += (s, n) => {
                progressBar1.Value = n;
            };
            var tt = Task.Run(()=>MYThreadAsync(pp,cts.Token,500),cts.Token);
            try
            {
                await tt;
                if (tt.Exception == null)
                    listBox1.Items.Add("任务完成");
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("异常" + ex.Message);
            }
        }         
        private void button4_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }
        public  void MYThreadAsync(IProgress<int> progress, CancellationToken ct, int delay)
        {
            int p = 0;//进度
            while (p < 100 && ct.IsCancellationRequested == false)
            {
                p += 1;
                Thread.Sleep(delay);
                progress.Report(p);//这个方法将会触发ProgressChanged事件更新进度条
            }
        }

4858.com 87

陆. 定时达成任务

  无论是服务器依然客户端,都是有定时实现有个别职责的须求的。System.Timers.Timer类是二个不利的定时设置类,那个类能够抓住风浪,但它私下认可是在线程池中迷惑轩然大波,而不是在如今线程中抓住事件。Timer类的常用属性有AutoReset和Interval属性,AutoReset是获取或安装三个bool值,该值为true表示每一次间隔结束时都引发2遍Elapsed事件,false表示仅在第叁次间隔结束时引发1回该事件。Interval属性是获得或安装几次Elapsed事件的间隔时间,该值必须大于零并小于Int.马克斯Value,暗中认可值为十0纳秒。Timer类还有五个常用艺术那就是Start和Stop方法。

  还有三个System.Threading.Timer类,它也是在线程池中定时实施职分,它与前二个Timer类的区分是此类不选取事件模型,而是平昔通过TimerCallback类型的信托来达成的。该类的构造函数为:Timer(TimerCallback
callback,Object state,TimeSpan douTime,TimeSpan
period)。callback代表要推行的法子,state表示1个含有回调方法要运用的新闻的对象,dueTime是第三回调用回调方法以前延迟的日子,period表示每一次调用回调方法的光阴世隔,-一意味终止。那样创制对象后,第1遍到达dueTime延时时间会活动调用三次callback委托,现在每隔period时间距离调用一次。以下是那三种艺术的周转效果和源代码。4858.com 88

 

4858.com 89

     System.Timers.Timer timer;
        System.Threading.Timer threadtimer;
        private void button2_Click(object sender, EventArgs e)//Timers.Timer
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            int pro=0;
            timer = new System.Timers.Timer(500);
            timer.AutoReset = true;
            timer.Elapsed+= (obj, args) =>
            { 
                pro+=5;
                progressBar1.Value = pro;
            };
            timer.Start();
        }

       private void button5_Click(object sender, EventArgs e)
       {
           timer.Stop();
           listBox1.Items.Add("第一个已经停止");
       }
    //Threading.Timer类
       private void button1_Click(object sender, EventArgs e)
       {
           progressBar2.Maximum = 100;
           progressBar2.Value = 0;
           TimeSpan dueTime = new TimeSpan(0, 0, 0, 1);
           TimeSpan period = new TimeSpan(0, 0, 0, 0, 200);
           System.Threading.TimerCallback timecall = new TimerCallback((obj) => progressBar2.Value += 5);
           threadtimer = new System.Threading.Timer(timecall, null, dueTime, period);
       }

       private void button6_Click(object sender, EventArgs e)
       {
           threadtimer.Dispose();
           listBox1.Items.Add("第二个已经停止");
       }

4858.com 90

  这篇小说只总计了单个任务的异步执行的根基,还得继续深造多职责并行执行。若是有更好的技术或许与信用社使用相关的异步技术,希望园友能够建议自身一而再读书。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有