c# task添加顺序_C# Task详解

本文介绍了C#中的异步编程,包括Task和async/await的相关内容。Task作为线程池的增强版,提供更好的线程控制,包括创建、运行、阻塞方法如Wait、WaitAll、WaitAny。async/await使得异步编程更加简洁,通过Task的返回类型定义异步方法。文章通过实例展示了如何使用Task和async/await进行异步操作,强调了它们在提高程序效率和避免阻塞主线程方面的作用。
摘要由CSDN通过智能技术生成

C# Task和async/await详解

什么是异步

同步和异步主要用于修饰方法。当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。

异步的好处在于非阻塞(调用线程不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执行,可以提高程序的运行效率。net4.0在ThreadPool的基础上推出了Task类,微软极力推荐使用Task来执行异步任务,现在C#类库中的异步方法基本都用到了Task;net5.0推出了async/await,让异步编程更为方便。本篇主要介绍Task、async/await相关的内容,其他异步操作的方式会在下一篇介绍。

Task介绍

Task是在ThreadPool的基础上推出的,我们简单了解下ThreadPool。ThreadPool中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务,任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用。当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行。线程池能减少线程的创建,节省开销,看一个ThreadPool的栗子吧

static void Main(string[] args)

{

for (int i = 1; i <=10; i++)

{

//ThreadPool执行任务

ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => {

Console.WriteLine($"第{obj}个执行任务");

}),i);

}

Console.ReadKey();

}

上边的代码通过ThreadPool执行了10个任务,执行结果为:

ThreadPool相对于Thread来说可以减少线程的创建,有效减小系统开销;但是ThreadPool不能控制线程的执行顺序,我们也不能获取线程池内线程取消/异常/完成的通知,即我们不能有效监控和控制线程池中的线程。

1 Task创建和运行

我们知道了ThreadPool的弊端:我们不能控制线程池中线程的执行顺序,也不能获取线程池内线程取消/异常/完成的通知。net4.0在ThreadPool的基础上推出了Task,Task拥有线程池的优点,同时也解决了使用线程池不易控制的弊端。

首先看一下怎么去创建并运行一个Task,Task的创建和执行方式有如下三种:

static void Main(string[] args)

{

//1.new方式实例化一个Task,需要通过Start方法启动

Task task = new Task(() =>

{

Thread.Sleep(100);

Console.WriteLine($"hello, task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");

});

task.Start();

//2.Task.Factory.StartNew(Action action)创建和启动一个Task

Task task2 = Task.Factory.StartNew(() =>

{

Thread.Sleep(100);

Console.WriteLine($"hello, task2的线程ID为{ Thread.CurrentThread.ManagedThreadId}");

});

//3.Task.Run(Action action)将任务放在线程池队列,返回并启动一个Task

Task task3 = Task.Run(() =>

{

Thread.Sleep(100);

Console.WriteLine($"hello, task3的线程ID为{ Thread.CurrentThread.ManagedThreadId}");

});

Console.WriteLine("执行主线程!");

Console.ReadKey();

}

执行结果如下:

我们看到先打印"执行主线程",然后再打印各个任务,说明了Task不会阻塞主线程。上边的栗子Task都没有返回值,我们也可以创建有返回值的~task,用法和没有返回值的基本一致,我们简单修改一下上边的栗子,代码如下:

static void Main(string[] args)

{

1.new方式实例化一个Task,需要通过Start方法启动

Task task = new Task(() =>

{

return $"hello, task1的ID为{Thread.Cur

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值