首页 > 编程语言 >C#的await,async,task(新手向)

C#的await,async,task(新手向)

时间:2024-07-24 10:06:36浏览次数:11  
标签:Task Console Thread C# await task 线程 WriteLine async

async await task

首先搞清楚什么是同步什么是异步
Synchronize 同步
asynchronous 异步
相差也就是一个a,也可以理解为a开头的就是异步操作,
同步一般是:当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行
异步一般是:方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕

哲学上思考,同步更规则性,代码会很好的顺序执行一般不会出错。异步必然伴随着各种各样的情况,但是很明显在一些耗时操作的时候能帮助减少时间

以C#为例子进行具体的学习:C#中三个关键词并不是同时发布的,task最先在dotnet中使用,可见先搞懂task是很重要的

TASK

task建立在线程池的基础上,线程池也就是管理一堆线程的一东西,为什么需要进行管理呢,需要的时候创建不就行了吗?这里涉及到操作系统,创建一个线程带来的开销远大于保持一个线程需要的时候再用的开销大,而线程池并不是很高大上,功能仅仅是保存和分配线程这点功能,只用线程池不能控制线程池中线程的执行顺序,也不能获取线程池内线程取消/异常/完成的通知。
task可以说是一个线程池pro max,他添加了这些功能,但也是一次只能运行一个函数。

使用的的办法有3种
一:new一个新的task,当想要使用的时候myNewTask.Start()
实例如下
Task task = new Task(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");
});
task.Start();
二:创建并开启一个task,Task.Factory.NewStart()
实例如下
Task task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task2的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
});
三:Task.Run() 将任务放在线程池队列,返回并启动一个Task
Task task3 = Task.Run(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task3的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine("执行主线程!");
Console.ReadKey();
这是没有返回值的例子,有返回值的也很简单
比如
Task task = new Task(() =>
{
return $"hello, task1的ID为{Thread.CurrentThread.ManagedThreadId}";
});
task.Start();
Console.WriteLine(task.Result);

思考一下,可以知道,有返回值的情况下,获取result必然是会阻塞主线程的,不阻塞会引发会乱
另外提一嘴 ,有种奇怪的运行方式task.RunSynchronously();,这个会同步运行一个task。
在使用Tread的时候,一般使用Join来阻塞主线程,类似的,Task也有这类功能,并且还更加完善static void Main(string[] args)
{
Task task1 = new Task(() => {
Thread.Sleep(500);
Console.WriteLine("线程1执行完毕!");
});
task1.Start();
Task task2 = new Task(() => {
Thread.Sleep(1000);
Console.WriteLine("线程2执行完毕!");
});
task2.Start();
//阻塞主线程。task1,task2都执行完毕再执行主线程
       //执行【task1.Wait();task2.Wait();】可以实现相同功能
Task.WaitAll(new Task[]{ task1,task2});
Console.WriteLine("主线程执行完毕!");
Console.ReadKey();
}
Task也有类似的操作用来阻塞主线程:
一 waitAll
Task.WaitAll(new Task[]{ task1,task2});
这个函数接受一个Task数组,会一直阻塞直到里面的都执行完毕
二 wait
上面的例子中也可以写作
task1.Wait();
task2.Wait();
三 WaitAny
函数用法和一中的类似,不过是只要任意一个完成就会停止阻塞,用处也挺大但没这么大

管道
很多语言中都有相通的思想,比如golang 的管道channel,在C#异步编程中也有体现
CancellationTokenSource这个类用来控制一个Task什么时候停止
举例来说
CancellationTokenSource source = new CancellationTokenSource();
int index = 0;
//开启一个task执行任务
Task task1 = new Task(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep(1000);
Console.WriteLine($"第{++index}次执行,线程运行中...");
}
});
task1.Start();
//五秒后取消任务执行
Thread.Sleep(5000);
//source.Cancel()方法请求取消任务,IsCancellationRequested会变成true
source.Cancel();
在使用winform的时候,经常会遇到修改ui的操作,这个时候必须使用异步才能不阻塞ui线程,不然会让应用好像“卡了”一样,

二 await
首先需要说明清楚,Task是一个类,其子类有一个Result。并且Task不能像其他类一样简单的理解为一个有很多方法的结构体,我更倾向于将这个理解为一个“操作”,其内部有很多普通类没有的线程操作。一定要在前面加上await来调用,这个和函数很不一样
我认为这是一种比较好的调用范式
static async Task Main(string[] args)
{
// 开始异步读取文件
Task fileReadTask = GetContentAsync(Environment.CurrentDirectory + @"/test.txt");

    // 在读取文件期间处理用户输入
    Console.WriteLine("请输入您的名字:");
    string userName = Console.ReadLine();
    Console.WriteLine($"您好,{userName}!文件正在读取中,请稍等。");

    // 在读取文件期间执行计算任务
    Task<int> calculationTask = PerformSomeCalculationAsync();
    
    // 等待文件读取完成
    string content = await fileReadTask;
    Console.WriteLine("文件内容读取完成:");
    Console.WriteLine(content);

    // 等待计算任务完成
    int calculationResult = await calculationTask;
    Console.WriteLine($"计算任务完成,结果是:{calculationResult}");
    
    Console.ReadKey();
}

// 异步读取文件内容
async static Task<string> GetContentAsync(string filename)
{
    using (FileStream fs = new FileStream(filename, FileMode.Open))
    {
        var bytes = new byte[fs.Length];
        Console.WriteLine("开始读取文件");
        int len = await fs.ReadAsync(bytes, 0, bytes.Length);
        string result = Encoding.UTF8.GetString(bytes);
        return result;
    }
}

// 模拟一个异步计算任务
async static Task<int> PerformSomeCalculationAsync()
{
    Console.WriteLine("开始计算任务...");
    await Task.Delay(3000); // 模拟一个耗时的计算
    Console.WriteLine("计算任务进行中...");
    return 42; // 假设计算结果是42
}
在这个例子中能像同步编程一样使用异步编程,只需要多声明一下Task和await,async
这背后有一个复杂的任务调度和上下文恢复机制,dotnet是很复杂的,我作为C# 的初学者并没有能够具体搞懂其中的奥妙,但是我可以简单的理解为,定义了Task之后,可以由await进行调用,并且与之相关的一系列代码都会进入一个新的线程中完成,主线程会绕过与之相关的代码,去完成接下来的任务,至于async,很遗憾我也不能解释清楚,但是显然的是,使用了这一套方法的函数和普通函数相当不一样,内部有一套自己的处理逻辑,async更像是告诉编译器的一种声明("你对我要特殊对待")

标签:Task,Console,Thread,C#,await,task,线程,WriteLine,async
From: https://www.cnblogs.com/yangxiaoshuai/p/18320223

相关文章

  • windows USB 设备驱动开发-USB Type-C 手动互操作性测试过程
    驱动开发中,可能需要测试已启用USBType-C的系统和Windows的互操作性。本文为设备和系统制造商提供了指南,用于对公开USBType-C连接器的系统和设备执行各种功能和压力测试。它假定读者熟悉官方USB规范和xHCI互操作性测试过程,可从USB.ORG下载。可以使用USBType-C......
  • 【云原生】Kubernetes 中的 PV 和 PVC 介绍、原理、用法及实战案例分析
    ✨✨欢迎大家来到景天科技苑✨✨......
  • c++_爆刷n题
    P1089[NOIP2004提高组]津津的储蓄计划题目描述津津的零花钱一直都是自己管理。每个月的月初妈妈给津津300300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同。为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上20%20%......
  • 【稳定检索|投稿优惠】2024年金融创新与当代贸易国际会议(ICFICT 2024)
    2024年金融创新与当代贸易国际会议2024InternationalConferenceonFinancialInnovationandContemporaryTrade【1】大会信息会议名称:2024年金融创新与当代贸易国际会议会议简称:ICFICT2024大会时间:请查看官网大会地点:中国·南京截稿时间:请查看官网审稿通知:投稿......
  • 蓝海项目短剧CPS如何快速搭建?
    短剧cps也就是短剧分销平台,是一种基于推广效果的分成模式平台。具体来说,它是指通过推广平台上的短剧内容,根据用户观看短剧后产生的实际充值或消费行为,平台会按照预先设定的比例来计算并支付推广佣金给推广者。这种模式主要应用于各个短视频平台、直播平台、播放平台等。那么......
  • pg 关于表膨胀 转发:https://www.cnblogs.com/lottu/p/14549463.html
    对于PostgreSQL处理MVCC(数据文件中新增tuple)的方式;相比其他数据库(Oracle、Mysql)而言;更容易触发表/索引膨胀。因为update操作也会影响表膨胀的问题。PostgreSQL处理的方式是对表autovacuum,vacuum是不会降低水位线。能避免表、索引膨胀。vacuumfull,reindex才会降低水位线。当然......
  • JAVA导出Excel文档水印包含中文变成乱码了(变成口了)
     在服务器执行下 fc-list:lang=zh如果为空说明没有中文字体,所以中文没法渲染,这样的话只能在项目里面自己引入字体 伪代码如下//加载外部字体文件Fontfont=null;try{InputStreamawardFontFile=Thread.currentThread().getCo......
  • docker的意义和安装方法
    docker就像一个集装箱,可以把你写的代码、软件等打包带走,走到哪都能用,不用担心环境问题。安装方法:Linux:1.更新系统:sudoaptupdate(Ubuntu/Debian)或sudoyumupdate(CentOS/Fedora)2.安装Docker引擎:curl-fsSLhttps://get.docker.com-oget-docker.sh&&shget-doc......
  • 开源WAF:ModSecurity探究与部署
    零、防火墙观察nginx日志发现恶意扫描什么/shell#$%*调研方案很多,但部分收费,收费的功能多但也比较耗费服务器,这里使用经典的web防火墙ModSecurity3一、ModSecurity3.0介绍ModSecurity是一个开源的跨平台Web应用程序防火墙(WAF)引擎,用于Apache,IIS和Nginx,由Trustwave的SpiderLab......
  • 如何找到 Cech 复合体在 1 维上具有持久同源性但 Vietoris Rips 复合体没有的点集?
    我尝试解决的练习:“找到一个点集,使得Cech复合体在1维上具有持久同源性,而VietorisRips复合体则没有。通过计算两个复合物的持久同源性来验证您的解决方案。“这可能吗?据我所知,这两个复合体在欧几里得子空间上重合。我可以改变云的度量,但这感觉就像作弊。我想......