写点什么

.NET8.0 多线程编码结合异步编码示例

  • 2025-01-15
    福建
  • 本文字数:2172 字

    阅读完需:约 7 分钟

1、创建一个.NET8.0 控制台项目来演示多线程的应用



2、快速创建一个线程



3、多次运行程序,可以得到输出结果




这就是多线程的特点 - 当多个线程并行执行时,它们的具体执行顺序是不确定的,除非我们使用同步机制(如 lock、信号量等)来控制执行顺序。


4、新建一个类 TestThread,以及一个静态的测试方法,用来做测试使用



5、在 Program 中,把输出改成调用 TestThread 类中的测试方法再次执行测试一下



6、执行以后的输出结果,如下图所示



7、Thread.Sleep(毫秒):线程的等待(睡眠)




执行结果:



8、Thread.Join() 代表线程执行完毕以后,才可以继续执行后续的代码



如下图所示,在 thread 线程内部执行完成以后,很快就接着执行最后的打印输出方法了



9、Thread.Join(毫秒) 代表等待当前线程执行多长时间,如果超出设定的毫秒数,就会直接执行后续的代码




运行程序,查看执行结果




1、新增 Test2 方法,用来测试线程池 ThreadPool 使用



2、WaitCallback 也是一个委托,传入需要在线程池内执行的方法名称。以下代码内,“线程池”字符串为要执行方法对应的参数



ThreadPool:这是.NET中的线程池类它维护着一组可重用的线程比直接创建新线程更有效率
QueueUserWorkItem:这个方法用于将工作项添加到线程池队列中线程池会自动分配空闲线程来执行这些工作项
WaitCallback:这是一个委托类型定义了线程池中的线程要执行的方法可以接收一个 object 类型的参数
TestThread.Test2:这是你定义的要在线程池中执行的方法它有这样的签名:public static void Test2(object state)
"线程池":这是传递给 Test2 方法的参数
复制代码


3、除了直接传入回调方法,也可以直接在线程池开启的方法内,直接写代码块来当做多线程执行的部分




4、线程池内,可以通过设置 Manual 信号量,来识别线程池内的线程什么时候执行完成。





**1、创建一个 TestAsyncAction 类,添加一个模拟的异步方法 TestAction



2、使用 Task 快读创建一个线程。最简单的方法:Task.Run(()=>{ 代码块 })



3、两个线程并行执行,查询执行结果



4、如果想等待新开线程执行完再继续执行后续的代码,可以使用如下方式:使用 await 等待整个操作完成


await Task.Run(async () =>{   await TestAsyncAction.TestAction();});
代码会等待异步操作完成才继续执行
复制代码


执行结果:



5、也可以使用 Task.Factory 创建一个任务工厂来实现



6、查看执行结果




1、【异步结合多线程】如果有多个任务在执行期间,在任意一个线程执行完毕以后进行执行某种操作,可以使用 ContinueWhenAny 来进行


// See https://aka.ms/new-console-template for more informationusing MultiThreading;
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}>>>>Hello, World!");

var tasks = new Task[3];
TaskFactory factory = new();
/* * .Unwrap() 主要是用来处理嵌套任务问题。 * 使用 StartNew 执行 async lambda 时,会得到一个 Task<Task> (双层嵌套的Task) * // 不使用 Unwrap var task1 = factory.StartNew(async () => { await Task.Delay(1000); return "Hello"; }); // task1 的类型是 Task<Task<string>> // 需要两次 await string result1 = await (await task1); --------------------------------------------------- // 使用 Unwrap var task2 = factory.StartNew(async () => { await Task.Delay(1000); return "Hello"; }).Unwrap(); // task2 的类型是 Task<string> // 只需要一次 await string result2 = await task2; */tasks[0] = factory.StartNew(async () =>{ await TestAsyncAction.AsyncAction1();}).Unwrap();
tasks[1] = factory.StartNew(async () =>{ await TestAsyncAction.AsyncAction2();}).Unwrap();
tasks[2] = factory.StartNew(async () =>{ await TestAsyncAction.AsyncAction3();}).Unwrap();
_ = factory.ContinueWhenAny(tasks, x =>{ Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}>>>>正常代码");});
Console.ReadLine();//阻止程序退出
PS:如果后续代码依赖于续联任务的完成,使用 await 如果不关心续联任务何时完成,使用 _=
复制代码


查看执行结果:



2、【异步结合多线程】如果要等任务全部执行完毕以后才执行某个代码块,可以使用 ContinueWhenAll



查看执行结果:



PS:// 可以使用 Task.WhenAny 替代 ContinueWhenAny_ = Task.WhenAny(tasks).ContinueWith(t => {    Console.WriteLine(">>>>正常代码");});
复制代码


3、异步方法中 使用 WhenAll 和 WhenAny(这个仅模拟纯 IO 操作,不涉及多线程)


  当遇到 await 时,当前方法会返回到调用者  主线程可以继续处理其他工作(比如UI响应、处理其他事件等)  这些任务会被放到线程池中执行
当前方法内 await 后面的代码会被打包成续接(continuation) 这个续接会等待所有任务完成后才执行 但这个等待是异步的,不会占用主线程资源
复制代码


  • .WhenAll()



查看执行结果:



  • .WhenAny()



查看执行结果:



文章转载自:sq1201

原文链接:https://www.cnblogs.com/sq1201/p/18664227

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
.NET8.0多线程编码结合异步编码示例_Java_不在线第一只蜗牛_InfoQ写作社区