当前位置: 首页 > news >正文

C#异步和多线程,Thread,Task和async/await关键字--12

目录

一.多线程和异步的区别

1.多线程

2.异步编程

多线程和异步的区别

二.Thread,Task和async/await关键字的区别

1.Thread

2.Task

3.async/await

三.Thread,Task和async/await关键字的详细对比

1.Thread和Task的详细对比

2.Task 与 async/await 的配合使用

3. async/await 的实际应用场景

4.关键区别总结


引言:在 C# 编程中,多线程和异步编程都是用于提高应用程序性能和响应性的技术,但它们的用途和实现方式有所不同

一.多线程和异步的区别

1.多线程

定义:

  • 多线程是指在一个应用程序中同时运行多个线程,每个线程都独立执行代码.这些线程可能在多个处理器核心上并行运行,也可能在单个核心上通过时间片轮转方式运行

特性:

  • 并行执行:多个线程可以并行执行任务,提高 CPU 利用率,适用于 CPU 密集型任务
  • 共享内存空间:同一进程中的线程共享内存空间,可以方便地共享数据,但也需要处理同步问题
  • 线程管理:需要开发者手动管理线程的创建,启动,同步和销毁

使用场景:

  • 需要并行处理多个 CPU 密集型任务,以充分利用多核 CPU 的能力
  • 需要在后台执行复杂计算,同时保持应用程序的响应性

2.异步编程

定义:

  • 异步编程是一种编程范式,允许程序在等待长时间运行的操作(如 I/O、网络请求)完成时,不阻塞当前线程,从而提高应用程序的响应性和效率

特性:

  • 非阻塞:异步操作不会阻塞线程,当前线程可以继续执行其他任务
  • 事件驱动:通过回调,事件或任务的方式在操作完成时通知应用程序
  • 适用于 I/O 密集型任务:特别是磁盘,网络等 I/O 操作,这些操作等待时间长,CPU 利用率低

使用场景:

  • 防止界面卡顿:在 GUI 应用程序中,防止长时间的操作阻塞 UI 线程,保持界面响应性
  • 服务器高并发:在服务器应用中,异步操作可以处理大量并发 I/O 请求,提高吞吐量

多线程和异步的区别

// 多线程示例
public void ThreadMethod()
{// 创建新线程Thread thread = new Thread(() =>{// 这段代码在新线程上运行DoSomeWork();});thread.Start();
}// 异步示例
public async Task AsyncMethod()
{// 不会创建新线程,而是在当前线程上异步执行await Task.Run(() =>{DoSomeWork();});
}
  • 目的不同:多线程主要用于并行执行 CPU 密集型任务,异步编程主要用于非阻塞地执行 I/O 密集型任务
  • 实现方式:多线程通过创建和管理线程实现并行,异步编程通过非阻塞的操作和回调机制实现,不一定需要多线程
  • 资源利用:多线程可能会创建大量线程,占用系统资源;异步编程通常使用回调或任务,不需要额外的线程
    // 多线程示例 - CPU密集型计算
    public void ThreadExample()
    {Thread calculateThread = new Thread(() =>{// 复杂计算for (int i = 0; i < 1000000; i++){// 进行大量计算}});calculateThread.Start();
    }// 异步示例 - I/O操作
    public async Task AsyncExample()
    {// 读取文件string content = await File.ReadAllTextAsync("file.txt");// 发送网络请求var response = await httpClient.GetAsync("http://api.example.com");
    }
    

二.Thread,Task和async/await关键字的区别

1.Thread

定义:

  • System.Threading.Thread 类表示 .NET 中的一个线程,可以用来手动创建,控制和管理线程

特性:

  • 直接映射到操作系统线程:每个 Thread 实例对应一个操作系统线程
  • 手动管理:需要手动创建,启动和销毁线程,以及处理线程同步问题
  • 开销较大:创建和销毁线程的开销较大,过多的线程可能导致系统性能下降

使用场景:

  • 需要对线程有精细的控制,比如设置线程优先级,堆栈大小,文化信息等
  • 特定场景下需要手动管理线程的生命周期

示例代码:

    // 创建第一个线程Thread thread1 = new Thread(() =>{for (int i = 0; i < 5; i++){Console.WriteLine($"线程1正在执行: {i}");Thread.Sleep(2000); // 暂停2秒}});// 创建第二个线程Thread thread2 = new Thread(new ThreadStart(Thread2Method));// 启动线程Console.WriteLine("开始执行线程...");thread1.Start();thread2.Start();// 等待线程结束//Join方法用于等待线程结束,即等待线程中的代码执行完毕。thread1.Join();thread2.Join();Console.WriteLine("所有线程执行完毕!");Console.ReadKey();
}// 第二个线程要执行的方法
static void Thread2Method()
{for (int i = 0; i < 5; i++){Console.WriteLine($"线程2正在执行: {i}");Thread.Sleep(800); // 暂停0.8秒}
}

2.Task

定义:

  • System.Threading.Tasks.Task 类代表一个异步操作,可以理解为更高级别的异步编程抽象

特性:

  • 基于任务的异步模式(TAP):使用任务来表示异步操作,可以更方便地组合,链接和处理任务
  • 线程池Task 默认会使用线程池中的线程,而不是创建新的线程,从而减少开销
  • 支持结果值Task<TResult> 可以返回计算结果
  • 与 async/await 协同工作Task 可以与 async/await 关键字配合使用,简化异步编程

使用场景:

  • 执行异步操作,无需手动管理线程。
  • 需要组合多个异步操作,或处理异步操作的结果。
     static async Task Main(string[] args){Console.WriteLine("开始任务示例...");// 1. 基本的异步任务await SimpleTaskAsync();// 2. 带返回值的任务int result = await CalculateAsync();Console.WriteLine($"计算结果: {result}");// 3. 并行任务await ParallelTasksAsync();// 4. 任务超时处理await TaskWithTimeoutAsync();Console.WriteLine("所有任务完成!");Console.ReadKey();}// 基本异步任务static async Task SimpleTaskAsync(){Console.WriteLine("开始简单任务");await Task.Delay(1000); // 模拟耗时操作Console.WriteLine("简单任务完成");}// 带返回值的异步任务static async Task<int> CalculateAsync(){Console.WriteLine("开始计算");await Task.Delay(2000); // 模拟复杂计算return 42;}// 并行任务示例static async Task ParallelTasksAsync(){Console.WriteLine("开始并行任务");var task1 = Task.Run(async () =>{await Task.Delay(1000);Console.WriteLine("任务1完成");});var task2 = Task.Run(async () =>{await Task.Delay(2000);Console.WriteLine("任务2完成");});// 等待所有任务完成await Task.WhenAll(task1, task2);Console.WriteLine("所有并行任务完成");}// 带超时的任务static async Task TaskWithTimeoutAsync(){Console.WriteLine("开始超时任务");try{using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));await Task.Delay(3000, cts.Token); // 这个任务会超时Console.WriteLine("此行不会执行");}catch (TaskCanceledException){Console.WriteLine("任务已超时");}}

3.async/await

定义:async/await是 C# 中用于简化异步编程的关键字

特性:

  • async 方法:使用 async 修饰的方法表示其内部可能包含异步操作,可以使用 await 关键字
  • await 关键字:用于等待一个异步任务完成,而不会阻塞当前线程
  • 编译器支持:编译器会将 async 方法转换为状态机,处理异步操作的调度

使用场景:

  • 希望以同步的方式编写异步代码,提高代码的可读性和维护性。
  • 在 GUI 或服务器应用中,防止长时间的操作阻塞线程。

三.Thread,Task和async/await关键字的详细对比

1.Thread和Task的详细对比

// Thread 示例
Thread thread = new Thread(() =>
{Console.WriteLine("使用 Thread 执行工作");Thread.Sleep(1000);
});
thread.Start();// Task 示例
Task task = Task.Run(() =>
{Console.WriteLine("使用 Task 执行工作");Thread.Sleep(1000);
});

主要区别:

Thread:

  • 直接映射到操作系统线程
  • 资源开销大
  • 无法直接返回结果
  • 不易于管理和组合

Task:

  • 使用线程池
  • 可以返回结果
  • 支持取消、延续、异常处理
  • 易于组合和管理

2.Task 与 async/await 的配合使用

// Task 单独使用
public Task<int> GetDataAsync()
{return Task.Run(() => {// 执行一些耗时操作Thread.Sleep(1000);return 42;});
}// 使用 async/await
public async Task<int> GetDataAsyncWithAwait()
{Console.WriteLine("开始");await Task.Delay(1000); // 异步等待Console.WriteLine("结束");return 42;
}

3. async/await 的实际应用场景

// 文件操作示例
public async Task SaveFileAsync(string content)
{Console.WriteLine("开始保存文件");await File.WriteAllTextAsync("test.txt", content);Console.WriteLine("文件保存完成");
}// 多个异步操作组合
public async Task ProcessDataAsync()
{try{// 并行执行多个异步操作var task1 = Task.Delay(1000);var task2 = Task.Delay(2000);await Task.WhenAll(task1, task2);// 串行执行异步操作var result1 = await GetDataAsync();var result2 = await ProcessResultAsync(result1);}catch (Exception ex){Console.WriteLine($"错误: {ex.Message}");}
}

4.关键区别总结

1)执行模型:

  • Thread: 一个线程执行一个任务
  • Task: 可以使用线程池,更灵活
  • async/await: 不创建新线程,而是管理异步操作

2)资源使用:

  • Thread: 每个线程占用约1MB内存
  • Task: 更轻量级,共享线程池
  • async/await: 几乎没有额外开销

3)使用场景:

  • Thread: 需要直接控制线程时
  • Task: 执行后台操作,需要返回结果时
  • async/await: IO操作,网络请求等不需要CPU计算的操作

4)代码可维护性:

  • Thread: 较难管理和维护
  • Task: 提供更好的控制和组合
  • async/await: 提供最清晰的代码结构

在实际的开发中优先使用 async/await 处理异步操作,需要并行计算时使用 Task,只在特殊情况下使用 Thread

相关文章:

C#异步和多线程,Thread,Task和async/await关键字--12

目录 一.多线程和异步的区别 1.多线程 2.异步编程 多线程和异步的区别 二.Thread,Task和async/await关键字的区别 1.Thread 2.Task 3.async/await 三.Thread,Task和async/await关键字的详细对比 1.Thread和Task的详细对比 2.Task 与 async/await 的配合使用 3. asy…...

使用分割 Mask 和 K-means 聚类获取天空的颜色

引言 在计算机视觉领域&#xff0c;获取天空的颜色是一个常见任务&#xff0c;广泛应用于天气分析、环境感知和图像增强等场景。本篇博客将介绍如何通过已知的天空区域 Mask 提取天空像素&#xff0c;并使用 K-means 聚类分析天空颜色&#xff0c;最终根据颜色占比查表得到主导…...

145.《redis原生超详细使用》

文章目录 什么是redisredis 安装启动redis数据类型redis key操作key 的增key 的查key 的改key 的删key 是否存在key 查看所有key 「设置」过期时间key 「查看」过期时间key 「移除」过期时间key 「查看」数据类型key 「匹配」符合条件的keykey 「移动」到其他数据库 redis数据类…...

Pytorch基础教程:从零实现手写数字分类

文章目录 1.Pytorch简介2.理解tensor2.1 一维矩阵2.2 二维矩阵2.3 三维矩阵 3.创建tensor3.1 你可以直接从一个Python列表或NumPy数组创建一个tensor&#xff1a;3.2 创建特定形状的tensor3.3 创建三维tensor3.4 使用随机数填充tensor3.5 指定tensor的数据类型 4.tensor基本运算…...

【SH】Xiaomi9刷Windows10系统研发记录 、手机刷Windows系统教程、小米9重装win10系统

文章目录 参考资料云盘资料软硬件环境手机解锁刷机驱动绑定账号和设备解锁手机 Mindows工具箱安装工具箱和修复下载下载安卓和woa资源包第三方Recovery 一键安装Windows准备工作创建分区安装系统 效果展示Windows和Android一键互换Win切换安卓安卓切换Win 删除分区 参考资料 解…...

excel仅复制可见单元格,仅复制筛选后内容

背景 我们经常需要将内容分给不同的人&#xff0c;做完后需要合并 遇到情况如下 那是因为直接选择了整列&#xff0c;当然不可以了。 下面提供几种方法&#xff0c;应该都可以 直接选中要复制区域然后复制&#xff0c;不要选中最上面的列alt;选中可见单元格正常复制&#xff…...

HBASE学习(一)

1.HBASE基础架构&#xff0c; 1.1 参考&#xff1a; HBase集群架构与读写优化&#xff1a;理解核心机制与性能提升-CSDN博客 1.2问题&#xff1a; 1.FLUSH对hbase的影响 2. HLog和memstore的区别 hlog中存储的是操作记录&#xff0c;比如写、删除。而memstor中存储的是写入…...

element select 绑定一个对象{}

背景&#xff1a; select组件的使用&#xff0c;适用广泛的基础单选 v-model 的值为当前被选中的 el-option 的 value 属性值。但是我们这里想绑定一个对象&#xff0c;一个el-option对应的对象。 <el-select v-model"state.form.modelA" …...

Sprint Boot教程之五十八:动态启动/停止 Kafka 监听器

Spring Boot – 动态启动/停止 Kafka 监听器 当 Spring Boot 应用程序启动时&#xff0c;Kafka Listener 的默认行为是开始监听某个主题。但是&#xff0c;有些情况下我们不想在应用程序启动后立即启动它。 要动态启动或停止 Kafka Listener&#xff0c;我们需要三种主要方法…...

C:JSON-C简介

介绍 JSON-C是一个用于处理JSON格式数据的C语言库&#xff0c;提供了一系列操作JSON数据的函数。 一、json参数类型 typedef enum json_type { json_type_null, json_type_boolean, json_type_double, json_type_int, json_type_object, json_type_ar…...

业务幂等性技术架构体系之消息幂等深入剖析

在系统中当使用消息队列时&#xff0c;无论做哪种技术选型&#xff0c;有很多问题是无论如何也不能忽视的&#xff0c;如&#xff1a;消息必达、消息幂等等。本文以典型的RabbitMQ为例&#xff0c;讲解如何保证消息幂等的可实施解决方案&#xff0c;其他MQ选型均可参考。 一、…...

【Go】Go Gin框架初识(一)

1. 什么是Gin框架 Gin框架&#xff1a;是一个由 Golang 语言开发的 web 框架&#xff0c;能够极大提高开发 web 应用的效率&#xff01; 1.1 什么是web框架 web框架体系图&#xff08;前后端不分离&#xff09;如下图所示&#xff1a; 从上图中我们可以发现一个Web框架最重要…...

2024年合肥市科普日小学组市赛第一题题解

9304&#xff1a;数字加密&#xff08;encrypt&#xff09;(1) 【问题描述】 在信息科技课堂上&#xff0c;小肥正在思考“数字加密”实验项目。项目需要加密n个正整数&#xff0c;对每一个正整数x加密的规则是&#xff0c;将x的每一位数字都替换为x的最大数字。例如&#xff0…...

【MySQL实战】mysql_exporter+Prometheus+Grafana

要在Prometheus和Grafana中监控MySQL数据库&#xff0c;如下图&#xff1a; 可以使用mysql_exporter。 以下是一些步骤来设置和配置这个监控环境&#xff1a; 1. 安装和配置Prometheus&#xff1a; - 下载和安装Prometheus。 - 在prometheus.yml中配置MySQL通过添加以下内…...

Wireshark 使用教程:网络分析从入门到精通

一、引言 在网络技术的广阔领域中&#xff0c;网络协议分析是一项至关重要的技能。Wireshark 作为一款开源且功能强大的网络协议分析工具&#xff0c;被广泛应用于网络故障排查、网络安全检测以及网络协议研究等诸多方面。本文将深入且详细地介绍 Wireshark 的使用方法&#x…...

如何在前端给视频进行去除绿幕并替换背景?-----Vue3!!

最近在做这个这项目奇店桶装水小程序V1.3.9安装包骑手端V2.0.1小程序前端 最近&#xff0c;我在进行前端开发时&#xff0c;遇到了一个难题“如何给前端的视频进行去除绿幕并替换背景”。这是一个“数字人项目”所需&#xff0c;我一直在冥思苦想。终于有了一个解决方法…...

使用中间件自动化部署java应用

为了实现你在 IntelliJ IDEA 中打包项目并通过工具推送到两个 Docker 服务器&#xff08;172.168.0.1 和 172.168.0.12&#xff09;&#xff0c;并在推送后自动或手动重启容器&#xff0c;我们可以按照以下步骤进行操作&#xff1a; 在 IntelliJ IDEA 中配置 Maven 或 Gradle 打…...

pytorch张量分块投影示例代码

张量的投影操作 背景 张量投影 是深度学习中常见的操作,将输入张量通过线性变换映射到另一个空间。例如: Y=W⋅X+b 其中: X: 输入张量(形状可能为 (B,M,K),即批量维度、序列维度、特征维度)。W: 权重矩阵((K,N),将 K 维投影到 N 维)。b: 偏置向量(可选,(N,))。Y:…...

Visual Studio 同一解决方案 同时运行 多个项目

方案一 方案二...

VMware中Ubuntu如何连接网络?安排!

一、设置NAT模式 1、关闭Ubuntu虚拟机&#xff1a; 确保Ubuntu已经完全关机&#xff0c;而不是挂起或休眠状态。 2、编辑虚拟网络设置&#xff1a; 在VMware主界面点击“编辑”菜单&#xff0c;选择“虚拟网络编辑器”。 如果需要&#xff0c;选择VMnet8 (NAT模式)并点击“更改…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...