(精华)2020年12月23日 .NET Core 多线程底层详解(异步发展史)

网友投稿 608 2022-05-29

第一阶段

线程有限多余的会固化到磁盘

public static class Sample01 { public static void Send(IPAddress address, int port) { var tcp = new TcpClient(); try { //C10K,10K个客户端,4G,10M,上 tcp.Connect(address, port); tcp.GetStream().Write(Encoding.ASCII.GetBytes("Hello")); } catch (Exception e) { Console.WriteLine(e); throw; } finally { tcp.Close(); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

第二阶段

基于回调的异步操作

public static class Sample02 { public static void Send(IPAddress address, int port) { var client = new TcpClient(); // 开始异步连接 client.BeginConnect(address, port, ar => { // 无论成功失败都会调用这个回调 try { client.EndConnect(ar); } catch (Exception e) { Console.WriteLine(e); client.Close(); } var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); stream.BeginWrite(bytes, 0, bytes.Length, result => { try { stream.EndWrite(result); } catch (Exception e) { Console.WriteLine(e); } finally { client.Close(); } },null); },null); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

第三阶段

Task TPL 任务并行库分离了异步操作与注册回调的处理,async和await

第一种,任务中执行指定的委托(运行时内部的线程池中运行),Run和Factory.StartNew

public class TplSample { public static Task SendAsync(IPAddress address, int port) { var client = new TcpClient(); // 异步连接 var task = client.ConnectAsync(address, port); var a = new TaskFactory(); // 异步发送数据 var task1 = task.ContinueWith(t => { var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); // 返回一个新的task // 这里会产生Task嵌套 // 在外部使用Unwrap方法解包 return stream.WriteAsync(bytes, 0, bytes.Length); }).Unwrap(); // 异步处理发送结果 var task2 = task1.ContinueWith(t => { if (t.IsFaulted) { // 失败 } else if (t.IsCompleted) { // 完成 } client.Close(); }); return task2; } public static void Run(IPAddress address, int port) { // 创建1万个Task var tasks = new Task[10000]; for (var i = 0; i < tasks.Length; i++) { // SendAsync 本身就是一个异步方法 tasks[i] = SendAsync(address, port); } // 等待所有异步操作执行完成 Task.WaitAll(tasks); } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

第二种,承诺对象,Promise,将来对象,Future

public class PromiseSample { public static Task ConnectAsync(TcpClient client,IPAddress address, int port) { // 创建一个承诺对象, var promise = new TaskCompletionSource(); // 获取将来对象 var future = promise.Task; client.BeginConnect(address, port, ar => { try { client.EndConnect(ar); promise.SetResult(null); } catch (OperationCanceledException) { promise.SetCanceled(); } catch (Exception ex) { promise.SetException(ex); } },null); return future; } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

task的异步

public static class ChildTaskSample { public static Task Run() { // 创建一个父任务 var parent = Task.Factory.StartNew(() => { // 创建子任务1 var child1 = Task.Factory.StartNew(() => { // 子任务1 },TaskCreationOptions.AttachedToParent); // 创建子任务2 var child2 = Task.Factory.StartNew(() => { // 子任务2 }, TaskCreationOptions.AttachedToParent); }); // 父任务会等待子任务1和2完成以后在调用回调 // 子任务中发生的异常也会传递到父任务的回调中 return parent; } }

1

(精华)2020年12月23日 .NET Core 多线程底层详解(异步发展史)

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

async和await

public static class Sample06 { // async关键字是给编译器看的,我就要为生产状态机 public static async Task SendAsync(IPAddress address, int port) { var client = new TcpClient(); try { // 异步连接 await client.ConnectAsync(address, port); // 连接成功后会从这里继续开始执行 // 失败时会抛出异常并在下面的catch块中被捕捉 var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); // 异步发送数据 await stream.WriteAsync(bytes, 0, bytes.Length); // 发送成功后会从这里继续开始执行 // 失败时同样会抛出异常,也在下面的catch块中被捕捉 Console.WriteLine("发送完成"); } catch (Exception e) { Console.WriteLine(e); } finally { client.Close(); } } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

备注:其他异步

ValueTask

从数据库随机取一条数据

先从数据库随机获取100条数据,作为将来100次调用的返回结果,每100次调用只有一次会查询数据库,其它99次都是同步完成

.NET 任务调度 多线程

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Linux ln命令
下一篇:P12.3-VueCLI3创建项目
相关文章