异步编制程序,走进异步编制程序的社会风气

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

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

一、简介

[C#] 异步编制程序,

  那是上篇《走进异步编制程序的世界 – 开端接触 async/await
异步编制程序》(入门)的第一章内容,主假若与我们齐声深刻钻探下异步方法。

  本文供给了然委托的应用。

 

  那是上篇《走进异步编制程序的社会风气 – 开头接触 async/await
异步编制程序》(入门)的第一章内容,首要是与大家一齐深远研讨下异步方法。

  本文供给明白委托的施用。

 

  首先来看看.net的前进中的各类阶段的表征:NET 与C#
的各样版本发表都以有四个“主题”。即:C#一.0托管代码→C#2.0泛型→C#3.0LINQ→C#四.0动态语言→C#4.5异步编程

解析异步方法

目录

  • 介绍异步方法

  • 控制流

  • await
    表达式

  • How
    撤除异步操作

 

目录

  • 介绍异步方法

  • 控制流

  • await
    表达式

  • How
    撤废异步操作

 

 

  那是上篇《开首接触 async/await
异步编程》(入门)的第1章内容,主倘使尖锐摸底异步方法,提出大家先看入门篇,极短。

  本文要求领悟委托的行使。

 

介绍异步方法

     异步方法:在推行到位前及时回到调用方法,在调用方法继续推行的经过中完结任务。

     语法分析:

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

     (二)供给:包蕴N(N>0) 个 await 表明式(不设有 await 表明式的话 IDE
会发出警告),表示要求异步实行的职责。【备注】谢谢 czcz1024 的匡正与互补:未有的话,就和常常方法一致进行了。

     (3)重临类型:只好回去 三体系型(void、Task 和 Task<T>)。Task 和 Task<T>
标记再次来到的指标会在以后达成工作,表示调用方法和异步方法能够继续实施。

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

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

     (陆)其它:匿超级模特式和 Lambda
表明式也足以视作异步对象;async 是几个上下文关键字;关键字 async
必须在重临类型前。

 

美高梅开户网址 1图1异步方法的简约结构图

  关于 async 关键字:

  壹在回来类型此前包蕴 async 关键字

  贰它只是标记该方法包蕴一个或多个 await
表达式,即,它自身不创制异步操作。

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

 

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

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

美高梅开户网址 2美高梅开户网址 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

美高梅开户网址 4美高梅开户网址 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 

美高梅开户网址 6

图2

美高梅开户网址 7

图3

 

  (贰)Task:调用方法不供给从异步方法中取重回值,可是希望检查异步方法的情事,那么能够选拔能够再次来到Task 类型的靶子。但是,固然异步方法中带有 return
语句,也不会回去任何事物。

美高梅开户网址 8美高梅开户网址 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

美高梅开户网址 10美高梅开户网址 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

 

美高梅开户网址 12

 

图4

美高梅开户网址 13

图5

     

  (3)void:调用方法实施异步方法,但又不须要做越发的互动。 

美高梅开户网址 14美高梅开户网址 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

美高梅开户网址 16美高梅开户网址 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

美高梅开户网址 18

图6

美高梅开户网址 19

图7

 

介绍异步方法

     异步方法:在实行到位前及时再次来到调用方法,在调用方法继续实行的历程中成就任务。

     语法分析:

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

     (贰)必要:包涵N(N>0) 个 await 表明式(不存在 await 表达式的话 IDE
会发出警示),表示须要异步实践的职务。【备注】谢谢 czcz1024 的匡正与互补:未有的话,就和平时方法相同实行了。

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

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

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

     (陆)此外:匿名方式和 Lambda
表达式也得以视作异步对象;async 是四个上下文关键字;关键字 async
必须在回来类型前。

 

美高梅开户网址 20图1 异步方法的简短结构图

  关于 async 关键字:

  壹在回去类型此前包涵 async 关键字

  二它只是标记该办法包罗一个或多个 await
表明式,即,它自身不创立异步操作。

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

 

  以往先来简单分析一下这三种回到值类型:void、Task 和 Task<T>

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

美高梅开户网址 21美高梅开户网址 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

美高梅开户网址 23美高梅开户网址 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 

美高梅开户网址 25

图2

美高梅开户网址 26

图3

 

  (贰)Task:调用方法不供给从异步方法中取再次来到值,可是希望检查异步方法的图景,那么能够选用能够重回Task 类型的目的。但是,就算异步方法中带有 return
语句,也不会回去任何事物。

美高梅开户网址 27美高梅开户网址 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

美高梅开户网址 29美高梅开户网址 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

 

美高梅开户网址 31

 

图4

美高梅开户网址 32

图5

     

  (叁)void:调用方法实践异步方法,但又不需求做进一步的相互。 

美高梅开户网址 33美高梅开户网址 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

美高梅开户网址 35美高梅开户网址 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

美高梅开户网址 37

图6

美高梅开户网址 38

图7

 

  上边作者来总结的介绍一下异步编程:异步编制程序,在 .NET Framework 4.伍 和
Windows 运转时选择异步扶助。
编写翻译器可实行开荒职员曾开始展览的高难度职业,且应用程序保留了3个近乎于同台代码的逻辑结构。
由此,你只需做一小部分工作就足以获得异步编制程序的装有好处。 

目录

 

一、控制流

     异步方法的协会可拆分成五个例外的区域:

     (一)表明式从前的有个别:从点子头到第二个await 表明式之间的具有代码。

     (二)await
表明式:将被异步实施的代码。

     (三)表明式之后的部分:await
表明式的承接部分。

 美高梅开户网址 39

  图1-1

 

  该异步方法试行流程:从await表明式从前的地方起初,同步执行到首个await,标记着第壹部分举行完结,一般的话此时 await 工作还没成功。当await
任务达成后,该措施将两次三番联合实行后续部分。在实行的持续部分中,假使依然存在
await,就再次上述进程。

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

 

美高梅开户网址 40

  图1-2

  异步方法的调整流:

  一异步实施 await 表达式的闲暇职务。

  二await 表明式试行到位,继续施行后续部分。如再相见 await
表明式,按同样意况举办处理。

  叁到达末尾或境遇 return 语句时,根据重回类型能够分三种情形:

    a.void:退出调节流。

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

    c.Task<T>:设置 Task
的质量和重临值(Result 属性)并退出。

  四并且,调用方法将继续实施,从异步方法赢得 Task
对象。要求值的时候,会中断等到 Task 对象的 Result
属性被赋值才会继续实施。

 

  【难点】

  一首先次遇上 await
所重临对象的体系。那个重临类型就是一道方法头的回到类型,跟 await
表明式的再次来到值未有关联。

  二达到异步方法的结尾或境遇 return
语句,它并不曾真正的回到三个值,而是退出了该格局。

 

一、控制流

     异步方法的协会可拆分成四个差别的区域:

     (一)表明式以前的有的:从点子头到第叁个await 表达式之间的持有代码。

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

     (三)表达式之后的有个别:await
表明式的承接部分。

 美高梅开户网址 41

  图1-1

 

  该异步方法推行流程:从await表达式在此以前的地点初步,同步实行到第多个await,标记着第二有的实行实现,一般的话此时 await 工作还没形成。当await
义务成功后,该措施将持续联合执行后续部分。在实践的持续部分中,假若依然存在
await,就再次上述进程。

  当达到 await
表明式时,线程将从异步方法再次回到到调用方法。借使异步方法的回来类型为 Task
或 Task<T>,会创制3个 Task 对象,标记需求异步达成的任务,然后将
Task 再次来到来调用方法。

 

美高梅开户网址 42

  图1-2

  异步方法的调控流:

  一异步实施 await 表明式的空余任务。

  二await 表达式试行到位,继续实施后续部分。如再相见 await
表达式,按同样情况开始展览处理。

  3到达末尾或遭逢 return 语句时,依据重回类型能够分三种情景:

    a.void:退出调控流。

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

    c.Task<T>:设置 Task
的脾性和重临值(Result 属性)并退出。

  4并且,调用方法将继续施行,从异步方法赢得 Task
对象。须求值的时候,会搁浅等到 Task 对象的 Result
属性被赋值才会继续执行。

 

  【难点】

  一首先次遇到 await
所重临对象的品类。这些重回类型正是贰只方法头的归来类型,跟 await
表明式的再次回到值没有涉嫌。

  二达到异步方法的结尾或碰着 return
语句,它并从未真的的回到1个值,而是退出了该方法。

 

 

介绍异步方法

   
 异步方法:在实施到位前及时回去调用方法,在调用方法继续施行的历程中成功职责。
     语法分析:      (1)关键字:方法头使用 async 修饰。    
 (贰)需要:蕴含 N(N>0) 个 await 表明式(不设有 await 表达式的话
IDE
会发出警告),表示必要异步实践的天职。【备注】谢谢 czcz10二四 的订正与互补:未有的话,就和普通方法1致进行了。
     (3)重返类型:只好回去 三 种类型(void、Task 和
Task<T>)。Task 和 Task<T>
标记重临的对象会在以往做到工作,表示调用方法和异步方法能够继续奉行。    
 (4)参数:数量不限。但不能够利用 out 和 ref 关键字。    
 (5)命名约定:方法后缀名应以 Async 结尾。      (陆)其它:匿名情势和
Lambda 表达式也足以当作异步对象;async 是五个上下文关键字;关键字 async
必须在回到类型前。     关于 async 关键字:

  壹在回来类型从前包涵 async 关键字

  贰它只是标记该办法蕴涵一个或八个 await
表明式,即,它自身不创设异步操作。

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

 

  今后先来第二分析一下那三种回到值类型:void、Task 和 Task<T>

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

美高梅开户网址 43 1 private
static void Main(string[] args) 2 { 三 Task<int> t =
Calculator.AddAsync(一, 贰); 四 5 //平昔在办事 6 七Console.WriteLine($”result: {t.Result}”); 八 玖 Console.Read(); 10 } Program.cs
美高梅开户网址 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 

 

  (2)Task:调用方法不须要从异步方法中取再次来到值,不过期望检查异步方法的气象,那么能够选拔能够再次来到Task 类型的对象。可是,尽管异步方法中隐含 return
语句,也不会回来任何事物。

美高梅开户网址 45 1 private
static void Main(string[] args) 2 { 三 Task t = Calculator.AddAsync(一,
贰); 四 5 //一直在劳作 陆 7 t.Wait(); 8 Console.WriteLine(“AddAsync
方法试行到位”); 玖 拾 Console.Read(); 1一 } Program.cs
美高梅开户网址 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

美高梅开户网址 47

图4

美高梅开户网址 48

图5

     

  (3)void:调用方法实行异步方法,但又不须要做进一步的竞相。 

美高梅开户网址 49 1 private
static void Main(string[] args) 二 { 3 Calculator.AddAsync(一, 2); 四 5
//平昔在职业 陆 柒 Thread.Sleep(一千); //挂起壹分钟 8Console.WriteLine(“AddAsync 方法推行到位”); 9 十 Console.Read(); 1一 }
Program.cs
美高梅开户网址 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

美高梅开户网址 51

图6

美高梅开户网址 52

图7

 

二、await 表达式

  await 表明式钦命了3个异步推行的天职。私下认可意况,该职责在此时此刻线程异步施行。

  每多少个职分便是一个 awaitable 类的实例。awaitable 类型指包罗GetAwaiter() 方法的类型。

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

  最简便易行的法子是在格局中利用
Task.Run() 来创立一个 Task。【注意】它是在差别的线程上进行形式。

 

  让我们1块来看看示例。

美高梅开户网址 53美高梅开户网址 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

美高梅开户网址 55

图2-1

美高梅开户网址 56

图2-2

   上边 四 个 Task.Run() 都是选择了 Task Run(Func<TReturn> func)
情势来直接或直接调用 Guid.NewGuid()。

 

  Task.Run() 协理 四 中区别的嘱托项目所代表的诀窍:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

美高梅开户网址 57美高梅开户网址 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

美高梅开户网址 59

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

 

二、await 表达式

  await 表明式钦点了3个异步施行的职务。默许情状,该职责在近期线程异步实践。

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

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

  最简便的点子是在格局中动用
Task.Run() 来创建二个 Task。【注意】它是在不相同的线程上实行办法。

 

  让我们壹道来探视示例。

美高梅开户网址 60美高梅开户网址 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

美高梅开户网址 62

图2-1

美高梅开户网址 63

图2-2

   上面 肆 个 Task.Run() 都以利用了 Task Run(Func<TReturn> func)
格局来直接或间接调用 Guid.NewGuid()。

 

  Task.Run() 帮忙 4 中差异的寄托项目所代表的措施:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

美高梅开户网址 64美高梅开户网址 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

美高梅开户网址 66

图贰-三 Task.Run() 方法的重载

 

  所谓的异步编制程序是采纳CPU空闲时间和多核的风味,它所再次回到的Task或Task<TResult>是对await的3个答应,当职责实施完结后回去一个结果给接收者。那里看到这一个也许各位不太明白,无妨,下边会有教学。

一、控制流

     异步方法的布局可拆分成多少个不一致的区域:    
 (壹)表明式以前的有个别:从章程头到第二个 await 表明式之间的全体代码。  
   (2)await 表达式:将被异步实践的代码。    
 (三)表明式之后的片段:await 表明式的继承部分。   一 internal class
Program 二 { 三 private static void Main(string[] args) 四 { 5 var t =
Do.GetGuidAsync(); 陆 t.Wait(); 七 八 Console.Read(); 9 } 拾 11 1二 private
class Do 壹三 { 1四 /// <summary> 一伍 /// 获取 Guid 1陆 ///
</summary> 一柒 /// <returns></returns> 1八 private
static Guid GetGuid() //与Func<Guid> 包容 1玖 { 20 return
Guid.NewGuid(); 二一 } 22 2三 /// <summary> 二4 /// 异步获取 Guid 25
/// </summary> 贰六 /// <returns></returns> 二⑦ public
static async Task GetGuidAsync() 2八 { 2玖 var myFunc = new
Func<Guid>(GetGuid); 30 var t1 = await Task.Run(myFunc); 3一 3二 var
t二 = await Task.Run(new Func<Guid>(GetGuid)); 3叁 34 var t三 = await
Task.Run(() => GetGuid()); 35 36 var t4 = await Task.Run(() =>
Guid.NewGuid()); 三七 38 Console.WriteLine($”t一: {t一}”); 3玖Console.WriteLine($”t2: {t2}”); 40 Console.WriteLine($”t3: {t三}”); 四一Console.WriteLine($”t4: {t4}”); 4二 } 肆3 } 4四 } View Code

图2-1

图2-2

   下面 4 个 Task.Run() 都是利用了 Task Run(Func<TReturn> func)
情势。

 

  Task.Run() 协助 四中不相同的寄托项目所表示的不2秘技:Action、Func<TResult>、Func<Task>
和 Func<Task<TResult>>

美高梅开户网址 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,职分需终止操作并回到;该目标操作是不可逆的,且不得不选取(修改)2次,即该对象内的 IsCancellationRequested
属性被设置后,就无法改动。

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

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

 

  示例

美高梅开户网址 68美高梅开户网址 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

美高梅开户网址 70

图3-1

美高梅开户网址 71

图三-二 注释两行代码

美高梅开户网址 72

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

  上航海用体育场合是不调用 Cancel() 方法的结果图,不会吊销任务的实行。

 

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

美高梅开户网址 73

图3-四:去掉注释

美高梅开户网址 74

图叁-5:图3-一和图三-4的实践结果(去掉注释)

 

三、How 裁撤异步操作

   CancellationToken 和 CancellationTokenSource
那多个类允许你甘休推行异步方法。

  (1)CancellationToken
对象涵盖职责是不是被注销的新闻;即便该指标的习性 IsCancellationRequested

true,职务需终止操作并重临;该对象操作是不可逆的,且不得不动用(修改)3回,即该目的内的 IsCancellationRequested
属性被设置后,就不能够更动。

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

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

 

  示例

美高梅开户网址 75美高梅开户网址 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

美高梅开户网址 77

图3-1

美高梅开户网址 78

图三-二 注释两行代码

美高梅开户网址 79

图三-叁:图三-一和图三-贰的实施结果(注释两行代码)

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

 

  下图在 三 秒后调用 Cancel() 方法打消职分的施行:

美高梅开户网址 80

图叁-四:去掉注释

美高梅开户网址 81

图3-伍:图叁-一和图3-四的推行结果(去掉注释)

 

 

三、撤消异步操作

 

小结

  • 介绍异步方法的语法、两种不相同的回到值类型(void、Task 和
    Task<T>)和决定流程等。
  • 粗略常用的异步实施办法:Task.Run()。【注意】它是在分裂的线程上施行措施。
  • 怎么裁撤异步操作。

 

小结

  • 介绍异步方法的语法、三种差别的回来值类型(void、Task 和
    Task<T>)和垄断(monopoly)流程等。
  • 大概常用的异步施行形式:Task.Run()。【注意】它是在分裂的线程上实践措施。
  • 何以撤废异步操作。

 

2、使用表明

四、非凡处理

 

传送门

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

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

  GUI 篇:《走进异步编制程序的社会风气 – 在 GUI
中实施异步操作》

 


初稿链接:

 【参考】《Illustrated C# 2012》

传送门

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

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

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

 


初稿链接:

 【参考】《Illustrated C# 2012》

主意签名包括三个 Async 或 async 修饰符。

伍、在调用方法中联合地等候任务

 

 

6、在异步方法中异步地伺机职务

 

依据预订,异步方法的称谓以“Async”后缀结尾。

七、Task.Delay 方法

 

 

小结

 

回去类型为下列项目之1:

传送门

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

 


 

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

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

 

倘诺你的方法有操作数为 TResult 类型的回到语句,则为
Task<TResult>。

 

万壹您的主意没有回到语句或具有未有操作数的回来语句,则为 Task。

 

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

 

有关详细音讯,请参见本大旨后边的“重返类型和参数”。

 

艺术一般包蕴至少1个 await
表明式,该表明式标记三个点,在该点上,直到等待的异步操作完结章程技巧承接。
同时,将艺术挂起,并且控件再次回到到方法的调用方。(那里所谓的挂起正是上文所关联的应允,异步方法承诺会给调用方三个结实)

 

三、示例

  施行才是印证真理的特等路线。

 

 

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);

        }

    }

}

 

  示例介绍:

 

    一、这一个例子中有三种达成方式:(1)利用异步编制程序的措施完结(2)利用常见同步格局贯彻

 

    二、同时那些例子中贯彻了递归,那一个能够毫不思量,博主只是想证美素佳儿下在异步的景况下,递归是或不是有效而已,实验结果为有效。

 

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

 

  在动用10二线程编写端口扫描程序时,笔者要好以为同步和分明全数线程都试行完的年华是2个相比麻烦的题材。有园友评论说现在早就不手动创立thread对象了,而是一贯接纳Task异步格局,笔者的网络编程老师也讲到了异步编制程序的优越性。在求学了课本上的知识后,举行了一个总结分享给大家。从.NET四.5开端,用async和await关键字再拉长Task.Run是一个非常不利的异步编程模型。

1.await和async

  异步形式从才具上看正是运用委托来落到实处的,它的最重要利润是在异步实行的长河中,用户仍是能够操控UI分界面。使用Task类和利用Thread类有好些个1般的地点,Task类也是由此调用方法去落到实处3个职责的完毕,方法但是是命名方式或匿超情势,在施行进度中可选用async和await来促成异步实践。async是贰个修饰符,它不得不用在点子依遗闻件处理程序的签字中。对于措施可分为有再次来到值和无再次回到值二种处境,事件则唯有一种,如上边三条语句所示:

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

    private async Task MethodAsync();//无重临值的异步方法

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

  await是1个运算符,它象征等待异步施行的结果。也能够知道为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作为后缀,那样能够很通晓的接头这一个措施是异步方法照旧1道方法。

二. 开立任务

  创设职分也等于将任务与要进行的艺术联系起来,编写职责实行的不二等秘书技时,这么些情势既可以是壹块方法也足以是异步方法,还足以是匿名格局。施行异步方法时,必须用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);//实施进度中得以监听撤废通知

三. 停歇职分

  在试行职分时一定晤面世要求结束任务的状态,那里的终止告诉职责你要趁早停下来不再试行了,而不是一贯接发售毁职务实例。那里能够打个纵然,学生一同出去吃饭了,学生与先生都在班群里面,突然班群里老师说要让同学们聚集,假设全部同学都看出那几个音信,然后学生们初始出发,那样就足以正确的集聚。上边包车型客车例证有二个很关键的前提,那就是全部同学都要观察这一个音信,相当于学生是随时监听消息的。CancellationTokenSource类和CancellationToken结构用于落到实处二拾十六线程、线程池和Task职分的吊销操作,处理方式与地点的事例相似。创建的班群就是CancellationTokenSource对象,收到的打招呼正是CancellationToken对象。CancellationTokenSource用于创建撤除布告,CancellationToken则用来传播应裁撤操作的关照,当调用义务前,能够先创建撤消源对象CancellationTokenSource
cts=new CancellationTokenSource();,要是期待在30秒后自行发出裁撤通告,能够流传参数CancellationTokenSource(提姆eSpan.FromSeconds(30));CancellationToken
ct=cts.Token;,后一句代码是得到撤除的关照。CancellationTokenSource还有五个Cancel方法,将这几个脾性设为true时,该方法会将有所增加了吊销标识的CancellationToken对象的IsCancellationRequested属性都安装为true,那样撤除通告就传递到了正在实行的职分。

  任务收到撤除布告后,能够选拔二种方法来终止操作。第叁种办法是简轻松单的从委托重临。那种完毕方式接近于在调用职责的代码中1个bool值来代表打消文告,任务收到后就平素再次回到了。当使用那种方法时职责状态的重返值为TaskStatus.RanToCompletion枚举值,它象征平常完毕,而不是TaskStatus.Canceled枚举值。第三种艺术是在代码里引发OperationCanceledException非常,并将其传递到在其上呼吁了撤消的标识,采取那种方法收回的天职会调换为用Canceled枚举值表示的情状。达成引发那2个的首推办法是调用ct.ThrowIfCancellationRequestes();。以下是代码示例,写了2个winform程序,利用进程条来打消职分。第十个图是尚未引发那多少个时,程序退出for循环,实施前边的代码后重临了,第三张图是第叁种格局,引发了要命后一向跳转到catch语句块了。

美高梅开户网址 82

美高梅开户网址 83

美高梅开户网址 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 + "完成了");
        }

美高梅开户网址 85

四. 收获职责施行的景观

  在异步编制程序中,很备受关注职务实践的情事是3个可怜重要的参数。在任务的生命周期里,可以经过Status属性来博取职务试行的景况,当任务成功后还可以够透过职务属性知道职分到位的情况。可利用职分实例的Status属性获取职责施行的情景,任务实施的场地用TaskStatus枚举表示,以下是TaskStatus的枚举值:

Created:职务现已开首化,但平素不进入调度计划

WaitingForActivation:该职责已进入调度安排,正在守候被调度程序激活

WaitingToRun:该职分已被调度程序激活,但从未开端进行

Running:该职责正在周转,但尚无变成

RanToCompletion:该职务已经成功达成

Canceled:该职责由于被收回而到位,引发那3个或调用方已向该任务的CancellationToken发出功率信号

Faulted:该职务因为出现未经处理的不胜而成功

WaitingForChildrenToComplete:该职分自小编已成功,正等待附加的子义务到位

  职分实现意况皮之不存毛将焉附的性格有IsCompleted、IsCanceled和IsFaulted等属性,从单词意思上看简单精晓它们的意思,当中要留心IsCompleted属性表示义务是或不是做到,无论是不荒谬结束依然因为撤废或特别而成功都为成功。

5. 任务试行的进程

  有时候大家期待让某个异步操作提供进度通报,以便在分界面中显得异步操作实行的进程,能够用Progress<T>类来获得任务实行的速度。以下是使用情势里的Report方法将艺术内变量的值传回创制职分的轩然大波代码里,从而立异进程条的值。

美高梅开户网址 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事件更新进度条
            }
        }

美高梅开户网址 87

6. 定期达成职务

  无论是服务器照旧客户端,都是有定时完毕某些职分的急需的。System.Timers.Timer类是2个正确的定时设置类,那个类能够招引事件,但它暗中同意是在线程池中吸引风云,而不是在近期线程中迷惑轩然大波。Timer类的常用属性有AutoReset和Interval属性,AutoReset是收获或安装3个bool值,该值为true表示每趟间隔停止时都引发1回Elapsed轩然大波,false表示仅在第二遍间隔甘休时引发壹次该事件。Interval属性是赢得或设置三次Elapsed事件的间隔时间,该值必须大于零并小于Int.马克斯Value,暗中同意值为十0飞秒。Timer类还有八个常用艺术那就是Start和Stop方法。

  还有1个System.Threading.提姆er类,它也是在线程池中定期执行职分,它与前3个Timer类的区分是此类不使用事件模型,而是径直通过提姆erCallback类型的嘱托来落到实处的。该类的构造函数为:Timer(TimerCallback
callback,Object state,TimeSpan dou提姆e,TimeSpan
period)。callback代表要实施的办法,state代表3个富含回调方法要动用的音信的指标,dueTime是第壹遍调用回调方法以前延迟的光阴,period表示每一趟调用回调方法的时光距离,-一意味着终止。那样创造对象后,第一次达到dueTime延时时间会自行调用1次callback委托,未来每隔period时间间隔调用一回。以下是那三种艺术的运作效果和源代码。美高梅开户网址 88

 

美高梅开户网址 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("第二个已经停止");
       }

美高梅开户网址 90

  那篇作品只总括了单个任务的异步实施的底子,还得继续学习多职务并行推行。假诺有更加好的技能依然与企业应用有关的异步技艺,希望园友能够提议自个儿继续求学。

发表评论

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

网站地图xml地图