掌握 C# 多线程与异步编程

现代应用程序通常需要执行复杂的计算或处理 I/O 操作,这些操作可能会导致主线程阻塞,从而降低用户体验。C# 提供了多线程与异步编程的多种工具,让我们能够高效地并发处理任务。本文将介绍 C# 中的多线程与异步编程,包括 Thread 类、任务并行库、async 和 await 异步编程,以及并行循环和 PLINQ。


1. 线程基础(Thread 类)

在 C# 中,Thread 类用于创建和管理独立的执行路径。每个线程都在单独的 CPU 核心上运行,可以并发处理多个任务。以下是 Thread 类的基本用法:

using System;
using System.Threading;public class Program
{public static void PrintNumbers(){for (int i = 1; i <= 5; i++){Console.WriteLine(i);Thread.Sleep(500);  // 模拟工作负载}}public static void Main(){Thread thread = new Thread(PrintNumbers);thread.Start();  // 启动新线程for (int i = 10; i <= 15; i++){Console.WriteLine(i);Thread.Sleep(500);}}
}

在此示例中,主线程和新线程 thread 会并发执行,分别输出 1 到 5 和 10 到 15。

  • 优点Thread 类提供了对底层线程的直接控制。
  • 缺点:创建和管理大量线程的开销较大,并且不便于资源管理。

2. 任务并行库(Task Parallel Library)

任务并行库 (Task Parallel Library, TPL) 简化了多线程编程,提供了 Task 类来抽象和管理并发任务。Task 更轻量级,且由运行时负责资源调度。Task.Run 可用于并行执行任务。

using System;
using System.Threading.Tasks;public class Program
{public static void Main(){Task task = Task.Run(() =>{for (int i = 1; i <= 5; i++){Console.WriteLine($"Task: {i}");Task.Delay(500).Wait();  // 模拟工作负载}});task.Wait();  // 等待任务完成Console.WriteLine("Task completed.");}
}

使用 TPL 的好处是,Task 可以简化线程管理,减少代码的复杂性。Task.Wait() 用于等待任务完成,而 Task.WhenAll 和 Task.WhenAny 可以实现多个任务的同步或竞赛。


3. async 与 await 异步编程

C# 提供的 async 和 await 关键字可以帮助我们编写简洁且高效的异步代码。在异步方法中使用 await 可以让方法在等待异步任务完成时不阻塞主线程。

using System;
using System.Threading.Tasks;public class Program
{public static async Task PerformTaskAsync(){Console.WriteLine("Starting task...");await Task.Delay(2000);  // 异步等待Console.WriteLine("Task completed.");}public static async Task Main(){await PerformTaskAsync();Console.WriteLine("Program completed.");}
}

在这个示例中,PerformTaskAsync 是一个异步方法,使用 await Task.Delay(2000) 模拟异步任务执行。在等待时,主线程并不会被阻塞,可以处理其他任务。

  • 优点async 和 await 简化了异步代码编写,避免了回调地狱问题。
  • 应用场景:适合需要等待 I/O 操作、网络请求等长时间任务的场景。

4. 并行循环与 PLINQ

并行循环 和 PLINQ(Parallel LINQ) 是 C# 中并行处理数据集合的两种方式,它们在多核系统上能够显著提高处理速度。

并行循环

Parallel.For 和 Parallel.ForEach 可以并行地处理集合中的元素,适合用于处理计算密集型任务。

using System;
using System.Threading.Tasks;public class Program
{public static void Main(){Parallel.For(0, 5, i =>{Console.WriteLine($"Parallel loop: {i}");Task.Delay(500).Wait();  // 模拟工作负载});Console.WriteLine("Parallel loop completed.");}
}

在此示例中,Parallel.For 将 0 到 5 的迭代并行化执行。并行循环适用于处理大量数据的计算密集型任务。

PLINQ

PLINQ(Parallel LINQ)是 LINQ 的并行版本,它允许我们使用 LINQ 查询语法来处理集合,同时利用多核处理器并行执行查询。使用 .AsParallel() 即可将普通 LINQ 查询转为并行处理。

using System;
using System.Linq;public class Program
{public static void Main(){int[] numbers = Enumerable.Range(1, 10).ToArray();var squaredNumbers = numbers.AsParallel().Select(n => n * n).ToArray();foreach (var num in squaredNumbers){Console.WriteLine(num);}}
}

在此示例中,AsParallel() 将查询转换为并行操作,Select 中的运算会在多个线程上同时执行。这使得 PLINQ 特别适合处理大数据集的批量计算。


结论

C# 提供了多种方式来处理并发任务和异步操作,包括 Thread、任务并行库 (TPL)、async 和 await 异步编程、并行循环和 PLINQ。

  • Thread 类 提供了底层线程控制。
  • 任务并行库 (TPL) 简化了并发任务管理。
  • async 和 await 提供了简洁的异步编程支持,避免阻塞主线程。
  • 并行循环 和 PLINQ 适合处理计算密集型的集合数据。

通过掌握这些工具和技术,你可以编写高效、可扩展的多线程和异步 C# 程序,为用户提供更流畅的体验。


这篇博客介绍了 C# 中的多线程与异步编程基础。如果你有进一步的问题或需要更深入的示例,欢迎留言或联系我!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10.3学习

1.循环依赖 循环依赖其实就是循环引用&#xff0c;也就是两个或者两个以上的 Bean 互相持有对方&#xff0c;最终形成闭环。比如A 依赖于B&#xff0c;B又依赖于A Spring中循环依赖场景有: prototype 原型 bean循环依赖 构造器的循环依赖&#xff08;构造器注入&#xff09;…

PIKACHU | PIKACHU 靶场 XSS 后台配置

关注这个靶场的其他相关笔记&#xff1a;PIKACHU —— 靶场笔记合集-CSDN博客 PIKACHU 自带了一个 XSS 平台&#xff0c;可以辅助我们完成 XSS 攻击&#xff0c;但是该后台需要配置数据库以后才能使用。本教程&#xff0c;就是教大家如何配置 PIKACHU XSS 平台的。 PIKACHU XS…

资源《Arduino 扩展板4-单游戏摇杆》说明。

资源链接&#xff1a; Arduino 扩展板4-单游戏摇杆 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;AD工程、原理图、PCB。 3.内容展示 4.简述 该文件为PCB工程&#xff0c;采用AD做的。 该文件打板后配合Arduino使用&#xff0c;属于Arduino的扩展板。 该文件…

深度学习的应用综述

文章目录 引言深度学习的基本概念深度学习的主要应用领域计算机视觉自然语言处理语音识别强化学习医疗保健金融分析 深度学习应用案例公式1.损失函数(Loss Function) 结论 引言 深度学习是机器学习的一个子领域&#xff0c;通过模拟人脑的神经元结构来处理复杂的数据。近年来&…

k8s实战-2

k8s实战-2 一、Deployment1.多副本2.扩缩容3.自愈&故障转移4.滚动更新5.版本回退 二、Service1.ClusterIP2.NodePort 总结 一、Deployment Deployment 是 k8s 中的一个资源对象&#xff0c;用于管理应用的副本&#xff08;Pods&#xff09;。它的主要作用是确保集群中运行…

【Linux】进程替换、命令行参数及环境变量(超详解)

目录 进程替换 替换函数的含义 命令行参数 环境变量 PATH 进程替换 我们先看代码&#xff1a; 1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5 printf("process...begin!\n");6 7 execl("/usr/bin/ls","ls"…

论文翻译 | Model-tuning Via Prompts Makes NLP Models Adversarially Robust

摘要 近年来&#xff0c;NLP从业者集中于以下实践:(i)导入现成的预训练(掩码)语言模型;(ii)在CLS令牌的隐藏表示(随机初始化权重)上附加多层感知器;(iii)在下游任务(MLP-FT)上微调整个模型。这一过程在标准的NLP基准上产生了巨大的收益&#xff0c;但这些模型仍然很脆弱&#x…

尝试从 http://pypi.doubanio.com/simple 这个索引源安装 webdriver 时出现了问题

问题如下&#xff1a; WARNING: The repository located at pypi.doubanio.com is not a trusted or secure host and is being ignored. If this repository is available via HTTPS we recommend you use HTTPS instead, otherwise you may silence this warning and allow …

从介质失效看互联网时代的信息过载

来读一篇文章&#xff1a;90年代的硬盘已大规模变砖&#xff0c;没啥好担心的&#xff0c;好事。 结合我两年前的粗浅认知 互联网时代无信息&#xff0c;按照 “动” 的观念看&#xff0c;当信息越来越多&#xff0c;信息密度越来越大时&#xff0c;信息的寿命就会越来越短&am…

离线安装docker

背景描述 项目需要在研发环境虚拟机上安装docker部署应用。 所在的服务器是一个内网&#xff0c;无法访问到外网环境。 服务器OS版本是 麒麟V10 linux 安装docker 安装包下载 获取所需版本的docker binary包&#xff0c;官方链接https://download.docker.com/linux/stati…

CoRL 2024 麻省理工学院提出T3触觉Transformer,打破触觉感知的壁垒,重塑未来机器人

在智能机器人领域&#xff0c;触觉感知的研究正逐渐成为关注的焦点。然而&#xff0c;如何让机器人通过触觉更智能地感知和操作&#xff0c;依然是一个未解决的挑战。基于相机的触觉感知是一种通过在软弹性体下嵌入相机来捕获与环境的细粒度交互的感知方法&#xff0c;是最流行…

[Python学习日记-39] 闭包是个什么东西?

[Python学习日记-39] 闭包是个什么东西&#xff1f; 简介 闭包现象 闭包意义与作用 简介 在前面讲函数和作用域的时候应该提到过&#xff0c;当函数运行结束后会由 Python 解释器自带的垃圾回收机制回收函数内作用域已经废弃掉的变量&#xff0c;但是在 Python 当中还有一种…

MySQL--数据库约束(详解)

目录 一、前言二、概念三、数据库约束3.1 约束类型3.1.1 NOT NULL 约束3.1.2 UNIQUE (唯一&#xff09;3.1.3 DEFAULT&#xff08;默认&#xff09;3.1.4 PRIMARY KEY&#xff08;主键&#xff09;3.1.5 FOREIGN KEY&#xff08;外键&#xff09;3.1.6 CHECK 四、总结 一、前言…

Golang | Leetcode Golang题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; func fourSumCount(a, b, c, d []int) (ans int) {countAB : map[int]int{}for _, v : range a {for _, w : range b {countAB[vw]}}for _, v : range c {for _, w : range d {ans countAB[-v-w]}}return }

STM32新建工程-基于库函数

目录 一、创建一个新工程 二、为工程添加文件和路径 三、创建一个main.c文件&#xff0c;并调试 四、修改一些配置 五、用库函数进行写程序 1、首先加入一些库函数和头文件 2、编写库函数程序 一、创建一个新工程 我这里选择STM32F103C8的型号&#xff0c;然后点击OK。 …

如何提取b站的视频字幕,下载视频

打开视频地址 按F12打开—开发者工具 在开发者工具打开Network 过滤器关键字&#xff1a; 自动生成字幕&#xff1a;ai_subtitle 自制&#xff1a;json 打开/关闭字幕 刷新页面 找到字幕 点选字幕的respond 将方框中的内容复制&#xff1b; 复制到&#xff1a;https://www.drea…

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC 第一节 硬件解读第二节 CubeMX配置第三节 代码编写 第一节 硬件解读 STM32的ADC是12位&#xff0c;通过硬件过采样扩展到16位&#xff0c;模数转换器嵌入到STM32L071xx器件中。有16个外部通道和2个内部通道&#xf…

github双重验证(2FA)启用方法

一、双重验证-2FA 在去年看到过说github启用双重验证的通知&#xff0c;觉得做为一个普通开发者&#xff0c;可能没有这么快会要求启用。结果&#xff0c;今天早晨一来就收到了邮件&#xff0c;要求说在11月底完成2FA的认证&#xff0c;否则权限受限。真是无了语。所谓2FA好理…

CSS 实现楼梯与小球动画

CSS 实现楼梯与小球动画 效果展示 CSS 知识点 CSS动画使用transform属性使用 页面整体布局 <div class"window"><div class"stair"><span style"--i: 1"></span><span style"--i: 2"></span>…

jmeter学习(2)变量

1&#xff09;用户定义的变量 路径&#xff1a;添加-》配置元件-》用户定义的变量 用户定义的变量是全局变量&#xff0c;可以跨线程组被调用&#xff0c;但在启动运行时获取一次值&#xff0c;在运行过程中不再动态获取值。 注意的是&#xff0c;如果在某个线程组定义了全…