C#:多线程Task使用

news2025/12/14 20:54:13

一.Task与Thread

  • Task是架构在Thread之上的,也就是说任务最终还是要抛给线程去执行。
  • Task跟Thread不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。
  • Task是用于表示一个异步操作的抽象。它是一种轻量级的、可等待的对象,允许你在不阻塞当前线程的情况下执行操作
  • Task用途:可以用来处理各种耗时的操作,如文件I/O、网络请求、复杂的计算等,从而提高应用程序的响应性和性能。例如,在一个图形用户界面(GUI)应用程序中,使用Task来执行长时间的文件读取操作,这样在读取文件时,用户界面仍然可以响应用户的其他操作,如点击按钮、移动窗口等
  • Task为后台程序,前台程序执行完毕后,软件即可结束

二.Task是使用方法:

创建Task,无返回值的创建方法,使用Task 创建以及使用Lambda表达式创建:有返回值的创建方法,Task支持泛型编程

//方法一:
Task b = new Task(()=> Console.WriteLine(  "Task 2" ));
b.start;
//方法二
Task.Run(() =>
{
    Console.WriteLine("Task1");
});
//方法三:
 TaskFactory taskFactory = new TaskFactory();
 taskFactory.StartNew(() => { Console.WriteLine("工厂模式创建"); });

//有返回值
Task<int> taskWithResult = Task.Run(() =>
{
    return 42; // 返回一个整数结果
});
Console.WriteLine(taskWithResult.Result);

执行结果,Task创建的为后台程序,当主线程为前台程序,当前台程序执行完毕,程序结束,后台程序会出现没有执行的情况:

Task1
工厂模式创建
Task 2
42

使用以下程序进行测试:

static void Main(string[] args)
{
  
    Task.Run(() =>
    {
        Console.WriteLine("Task1");
    });
    TaskFactory taskFactory = new TaskFactory();
    taskFactory.StartNew(() => { Console.WriteLine("工厂模式创建"); });
    ///Task a =new Task(program.GetTicket);
    Task b = new Task(()=> Console.WriteLine(  "Task 2" ));
    b.Start();
    Console.WriteLine( "main主程序" );
}

执行结果如下:

//执行结果1:
main主程序
Task1
工厂模式创建
Task 2

//执行结果2:
main主程序
工厂模式创建
Task1

为了解决这个问题,Task提供一系列API进行线程控制:

Task API意义
Task.Result获取Task的返回值
Task.ContinueWith一个任务完成后执行
Task.Delay异步延迟程序,不会阻碍主线程
Task.Wait用与阻塞当前线程,直到指定任务完成,相当于Thread.Join()
Task.WaitAll等待列表中的任务全部完成,传递Array
Task.WaitAny等待列表中的任一任务全部完成,传递Array
Task.WhenAll等待列表中的任务都完成(异步),传递Array
Task.WhenAny等待列表中的任一任务完成(异步),传递Array

通过程序逐步演示该API使用方法:

Task task1 = new Task(()=> Console.WriteLine("Task1"));
Task task2 = task1.ContinueWith(t =>                  //t和task1为同一任务
 {
   Console.WriteLine(t ==task1);
   Console.WriteLine("task2");
  });
  task1.Start();
 // task2.Start();//持续线程不可以使用start
  task1.Wait();   //阻塞主线程,Task线程完成后在进行执行
  task2.Wait();   //阻塞主线程,Task线程完成后在进行执行
  Console.WriteLine( "main线程" );

打印结果:

Task1
True
task2
main线程
  • Continue with使用,参数t指的是上一个Task:

            Task<int> task1 = Task.Run(() =>
            {
                return 10086;
                Console.WriteLine("Task1 is Running"); } 
            );
            Task<int> task2 = task1.ContinueWith(t => { 
                return t.Result + 1;
                Console.WriteLine("Task2 is Running");
           
            });
            Task<int> task3 = task2.ContinueWith(t => {
                return t.Result + 1;
                Console.WriteLine("Task2 is Running");

            });
            Console.WriteLine( task3.Result  );
            Console.WriteLine( task1.Result );
            Console.WriteLine( task2.Result );

打印结果:

10088
10086
10087

三.async和await:

async执行一个异步方法,await执行一个异步任务,当程序遇见await会单独开一个控制流,不影响主线程的执行。

 static void Main(string[] args)
 {
     Console.WriteLine($"main方法Begins:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");
     RunAsync();
     Console.WriteLine($"main方法Ends:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");
     Console.ReadLine();
}

public static async void RunAsync() //异步方法必须使用async
{
    Console.WriteLine( $"RunAsync方法Begin:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}" );

//await开启异步任务
    await Task.Run(() =>
    {
        Console.WriteLine($"Task方法Begin:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");

        long sum = 0;
        for (long i = 0; i < 10000000000; i++) {
            sum += i;
        };
        Console.WriteLine();
        Console.WriteLine($"Task方法End:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");

    });


    Console.WriteLine($"RunAsync方法End:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");

}

打印结果:

main方法Begins:线程ID:1,是否在线程池False
RunAsync方法Begin:线程ID:1,是否在线程池False
main方法Ends:线程ID:1,是否在线程池False
Task方法Begin:线程ID:3,是否在线程池True

Task方法End:线程ID:3,是否在线程池True
RunAsync方法End:线程ID:3,是否在线程池True

使用async和await执行有返回值的方法,异步任务的返回值类型默认为Task,await作用有两个,分流和获取任务返回值的功能,没有await关键字,则相当于同步方法:

 static void Main(string[] args)
 {
     Console.WriteLine($"main方法Begins:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");
     RunAsync();
     Console.WriteLine($"main方法Ends:线程ID:{Thread.CurrentThread.ManagedThreadId},是否在线程池{Thread.CurrentThread.IsThreadPoolThread}");
     Console.ReadLine();
}

public static async void RunAsync() 
{
    long result=await GetSumAsync(); //必须使用await,getsum是任务,异步分流
    Console.WriteLine($"计算结果是:{result}");
}
public static async Task<long> GetSumAsync()
{
    return await Task.Run(() =>
    {
        long sum = 0;
        for (long i = 0; i < 1000000000; i++)
        {
            sum += i;
        }

        return sum;         
    });           
}

打印结果:

main方法Begins:线程ID:1,是否在线程池False
main方法Ends:线程ID:1,是否在线程池False
计算结果是:499999999500000000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2385331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

模拟电子技术基础----绪论

一、电子技术的发展 1.电子技术的发展&#xff0c;推动计算机技术的发展&#xff0c;使之“无孔不入”&#xff0c;应用广泛&#xff01; •广播通信&#xff1a;发射机、接收机、扩音、录音、程控交换机、电话、手机 •网络&#xff1a;路由器、ATM交换机、收发器、调制解调…

iOS 使用 - 设置 来电震动/关闭震动

来电震动是一个很直观的老功能。但到了iOS 18&#xff0c;苹果却把震动功能的开关藏得越来越深&#xff0c;甚至分散在不同的菜单里&#xff0c;让用户难以找到。这里记录分享设置方法&#xff1a; 1. 震动开关的路径 设置 → 通用 → 辅助功能 → 触控 → 震动 2. 来电震动…

[C语言初阶]扫雷小游戏

目录 一、原理及问题分析二、代码实现2.1 分文件结构设计2.2 棋盘初始化与打印2.3 布置雷与排查雷2.4 游戏主流程实现 三、后期优化方向 在上一篇文章中&#xff0c;我们实现了我们的第二个游戏——三子棋小游戏。这次我们继续结合我们之前所学的所有内容&#xff0c;制作出我们…

谷歌medgemma-27b-text-it医疗大模型论文速读:多语言大型语言模型医学问答基准测试MedExpQA

《MedExpQA: 多语言大型语言模型医学问答基准测试》论文解析 一、引言 论文开篇指出大型语言模型&#xff08;LLMs&#xff09;在医学领域的巨大潜力&#xff0c;尤其是在医学问答&#xff08;QA&#xff09;方面。尽管LLMs在医学执照考试等场景中取得了令人瞩目的成绩&#…

DeepSeek+白果AI论文:开启答辩PPT生成的「智能双引擎」时代

2025学术答辩革新&#xff1a;DeepSeek与白果AI论文的黄金协同方案 白果Ai论文&#xff0c;论文写作神器~ https://www.baiguoai.com/ 在学术答辩的「战场」上&#xff0c;「选题创新不足」「数据可视化低效」「PPT逻辑断裂」等痛点长期困扰研究者。DeepSeek与白果AI论文的深…

SDC命令详解:使用set_logic_dc命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 set_logic_dc命令可以将当前设计中的输入端口为不关心&#xff08;设置端口的driven_by_dont_care属性为true&#xff09;&#xff0c;该端口在综合是可以被认为是…

小程序涉及提供提供文本深度合成技术,请补充选择:深度合成-AI问答类目

一、问题描述 最近新项目AI咨询小程序审核上线&#xff0c;按照之前小程序的流程&#xff0c;之前审核&#xff0c;提示审核不通过&#xff0c;审核不通过的原因&#xff1a;小程序涉及提供提供文本深度合成技术 (如: AI问答) 等相关服务&#xff0c;请补充选择&#xff1a;深…

基于亚博K210开发板——lvgl 图形化实验

开发板 亚博K210开发板 实验目的 本次测试主要学习 K210 图形化操作界面的功能。 实验元件 LCD 显示屏、FT6236 触摸板 lvgl 图形化库简介 LVGL&#xff08;轻度综合图形界面库&#xff09;是一个免费开源图形库&#xff0c;具有使用方便&#xff0c;画面美观&#xff…

LABVIEW 通过节点属性动态改变数值显示控件的方法

在 LabVIEW 里&#xff0c;能够借助属性节点来改变数值输入控件的禁用状态。下面为你介绍具体的操作步骤&#xff1a; 1. 创建或开启前面板 要先创建一个数值输入控件&#xff0c;操作方法是&#xff1a;点击 "控件" 选板&#xff0c;接着选择 "新式→数值→数…

信息安全管理与评估2025上海卷

上海市“星光计划”第十一届职业院校技能大赛 &#xff08;高职组&#xff09; “信息安全管理与评估”赛项 任务书 一、 赛项时间共计4小时。二、 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备 配置防护 任务1 网络平台搭建 2…

Linux目录介绍+Redis部署(小白篇)

目录 &#x1f451;Linux基础✨【目录】 &#x1f451;Redis 安装1.下载压缩包2.解压3.安装编译环境4.安装到本地5.设置开机自启 &#x1f451;Linux 自启服务 &#x1f451;Linux基础 虽然在大二的时候学过Linux&#xff0c;但是很多基础知识都忘了&#xff0c;想再次从基础捡…

Python 基础语法速查手册:从入门到精通

Python 作为最受欢迎的编程语言之一&#xff0c;以其简洁易读的语法和强大的功能吸引了大量开发者。本文全面汇总 Python 基础语法知识&#xff0c;帮助初学者快速掌握核心概念&#xff0c;并为后续深入学习打下坚实基础。 1. Python 基础语法结构 1.1 代码结构与缩进规则 Py…

论文阅读笔记——Emerging Properties in Unified Multimodal Pretraining

BAGEL 论文 商业闭源系统与学术/开源模型的差距很大&#xff0c;BAGEL 旨在通过开源统一架构大规模交错数据主要解决&#xff1a; 架构割裂&#xff1a;理解/生成分属两条网络&#xff0c;信息被压缩在少量条件 token 中&#xff0c;长上下文推理受限。数据贫乏&#xff1a;主…

JAVA批量发送邮件(含excel内容)

EmailSenderHtmlV1 是读取配置文件《批量发送邮件.xlsx》&#xff0c;配置sheet获取 发件人邮箱 邮箱账号 口令&#xff0c;发送excel数据sheet获取收件人邮箱 抄送人邮箱 邮件标题 第N行开始(N>1,N0默认表头) 第M行结束(M>1,M0默认表头) 附件文件夹…

Linux(Ubuntu)新建文件权限继承问题

当你在一个工作目权限为777的文件下&#xff0c;新建一个文件的时候&#xff0c;就有可能发生&#xff0c;新建的这个文件&#xff0c;权限和其他文件&#xff0c;或者工作目录不一致的问题&#xff0c;我们不可能每次新建一个文件&#xff0c;就要 sudo chmod -R 777 /PATH 所…

Java中的String的常用方法用法总结

1.1 String &#xff08;1&#xff09;声明 &#xff08;2&#xff09;字符串常量 存储字符串数据的容器&#xff1a;private final char value[] 字符串常量都存储在字符串常量池&#xff08;StringTable&#xff09;中 字符串常量池不允许存放两个相同的字符串常量 &#xff…

QGIS如何打开 ARCGIS的mxd工程文件

“SLYR”是一款由著名开源组织“北路开源”开发的一套QGIS兼容和转换ARCGIS样式、工程、设置信息的插件&#xff01;其主要功能为&#xff1a; 最近项目需要&#xff0c;我使用了一些功能&#xff0c;发现其对中文环境及中文信息支持不太好&#xff0c;还有一些其它BUG&#xf…

基于微信小程序的智能问卷调查系统设计与实现(源码+定制+解答)基于微信生态的问卷管理与数据分析系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

React 如何封装一个可复用的 Ant Design 组件

文章目录 前言一、为什么需要封装组件&#xff1f;二、 仿antd组件的Button按钮三、封装一个可复用的表格组件 (实战)1. 明确需求2. 设计组件 API3. 实现组件代码4. 使用组件 三、封装组件的最佳实践四、进阶优化 总结 前言 作为一名前端开发工程师&#xff0c;在日常项目中&a…

Canvas SVG BpmnJS编辑器中Canvas与SVG职能详解

Canvas详解与常见API 一、Canvas基础 核心特性 • 像素级绘图&#xff1a;Canvas是基于位图的绘图技术&#xff0c;通过JavaScript操作像素实现图形渲染&#xff0c;适合动态、高性能场景&#xff08;如游戏、数据可视化&#xff09;。 • 即时模式&#xff1a;每次绘制需手动…