C#基础-多线程

同步与异步:.NET 中的 Task.WaitAll 和 Task.WhenAll Task.WaitAll 是一种同步方法,它会阻塞调用线程,直到所有提供的任务都已完成。当您需要确保一组任务在继续之前已完成时,该方法很有用,但它以阻塞方式执行,这意味着调用 Task.WaitAll 的线程会被占用,直到所有任务都完成为止。Task.WhenAll 是一种异步方法,当所有提供的任务都完成后,该方法将返回单个任务。与 Task.WaitAll 不同,它不会阻止调用线程。相反,它允许调用代码继续异步执行。 阅读详情

C# 多线程

闲得蛋疼,记录一下线程的基础概念和常规用法

基础概念

**进程:**应用程序(typerpa、word、IDEA)运行的时候进入到内存,程序在内存中占用的内存空间(进程)。

  • 是程序(任务)的一个执行过程,是动态的。
  • 持有资源(共享内存,共享文件)和线程。

线程:进程中负责程序运行的执行单元,也叫执行路径。

  • 可以将进程看作一个班级,线程看作班级里的学生,学生通过使用共享资源(教师、桌椅、黑板)进行学习。
  • 多线程技术解决了多部分代码同时执行的需求,能够更好的利用cpu的资源。

线程任务:线程执行的代码内容。

并行:多个cpu实例或者多台机器同时执行处理逻辑,实现真正的同时。

  • 如果电脑的CPU是多核处理器(4核),那就可以做到同时处理4个线程,从真正意义上做到多线程并行。线程的最大并行数量上限是CPU核心的数量,但是,往往电脑运行的线程的数量远大于CPU核心的数量,所以 还是需要CPU时间片的切换。

并发:通过cpu的调度算法,快速的切换线程执行线程任务,并不是真正意义上的同时。

线程安全:同一段代码在多线程使用下,不会因为线程的调度顺序而影响任何结果。在出现共享资源的情况下容易出现线程安全问题。确保线程的安全要优先于性能。

争用条件:当多个线程共享访问同一数据时,每个线程都尝试操作该数据,从而导致数据被破坏,这种现象称为争用条件。


注意,尽管多线程的使用可以提升程序的运行效率,充分发挥CPU的作用,但多线程并不是所有时候都可以随便使用的,多线程在时间和空间上都是有开销的,当超过一定限度之后,多线程开得越多,性能反而会下降。因此使用时应该根据实际需求,谨慎使用。

空间上的开销

  • Thread内核数据结构:线程的ID和线程环境都在CPU寄存器中占用空间。例如在CPU进行时间片切换的时候,没有处理完的数据会存储在CPU的相关空间中。
  • 用户堆栈模式:用户程序中的局部变量和参数传递所使用的堆栈。常见的异常:StackOverFlowException(堆栈溢出)就是内存占存过多,导致溢出异常。

时间上的开销

  • 资源使用通知的开销:因为一个程序会调用很多的托管和非托管的dll或exe资源,使用前需要先进行通知确认,这都是需要时间的。
  • 时间片切换开销。

Thread

一、线程的简单使用

在C#中启动多线程需要实例化一个 Thread对象,然后在构造方法中传入委托对象,为了方便一般会直接传入lambda表达式, 这个lambda表达式中执行的代码片段就是新的线程中所需要执行的任务。

最后,调用Thread对象Start()方法来启动新线程。

static void Main(string[] args)
{
    var thread = new Thread(() =>
    {
        Print();
    });
    thread.Start();
    Console.WriteLine($"主线程ID:{Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine("主线程结束!");
}

private static void Print()
{
    for (var i = 0; i< 100; i++)
    {
        Console.WriteLine($"子线程ID:{Thread.CurrentThread.ManagedThreadId}------{i}");
        Thread.Sleep(1000);
    }
}

另外提一下,因为线程的构造函数Thread()中所需要传入的参数是一个委托对象,所以如果任务函数不需要传入任何参数,可以直接将任务函数的名称作为参数传给构造函数。

var thread = new Thread(Print);

此外,如果需要提前终结线程,可以使用Thread对象的Abort()方法。

Abort():在调用此方法的线程上引发 System.Threading.ThreadAbortException,通过处理异常,去决定程序的终止与否(例如直接不理会异常导致整个程序终止),并不能直接终止线程。

  • 该方法已经过时弃用,不建议使用。

二、前台线程&后台线程

从上面的例子中可以看到,当程序运行起来后,主线程已经运行结束了,但是程序却没有停止,子线程依然在运行,依然每隔1秒输出一次。

这种情况下,持续运行的子线程就被称作前台线程(Foreground Thread)。

一般来说,在前台线程中执行的任务都比较重要,所以,只有等待所有的前台线程结束以后程序才能关闭。

相对而言,后台线程执行的任务就不是那么重要了,只要主线程和所有的前台线程执行结束,就算后台线程的任务还没完成,也会强行打断直接退出。

在 .Net中,除了主线程以外,任何一个线程都可以在任何时候在前台和后台之间随意切换。代码也非常简单,只需要将它的IsBackground属性设置为true,那么这个线程就可以被切换为后台线程了。

var thread = new Thread(() =>
{
    Print();
});
thread.IsBackground = true;
thread.Start();

特点:

后台线程不会影响进程的终止,属于某个进程的所有前台线程都终止后,该进程就会被终止,所有剩余的后台线程都会被强制停止。

可以在任何时候(线程开始前或开始后都可以)将前台线程修改为后台线程,方式是设置IsBackground属性。

不管是前台线程还是后台线程,如果线程内出现了异常,都会导致进程的终止。

托管线程池中的线程都是后台线程,使用new Thread方式创建的线程默认都是前台线程。

三、线程池

线程是非常消耗资源的,如果我们每次需要子线程来执行任务,就去创建一个新的线程,那当我们执行1千次1万次甚至是100万次的时候,那么估计电脑硬件也受不了这么大的资源消耗。

对于这种情况我们就需要使用线程池来管理线程了。只要是通过线程池创建的线程,那么它的所有的生命周期都会托管在线程池内。所有线程池中的线程都是后台线程,线程池会检查程序当前的运行状态,当程序启动时,线程池内的线程也会开始工作;而当Main方法结束以后,线程池会自动关闭,同时中断所有正在运行的线程。

线程池的使用方式很简单,直接调用线程池ThreadPool类中的静态方法QueueUserWorkItem()来创建线程池内的线程就可以了。

static bool QueueUserWorkItem(WaitCallback callBack):参数为一个带一个object类型参数的委托,最后返回bool值成功则返回true。

static void Main(string[] args)
{
    for(var i = 0; i<100; i++)
    {
        ThreadPool.QueueUserWorkItem((state) =>
        {
            Console.WriteLine($"子线程ID:{Thread.CurrentThread.Managed
C# 多线程详细讲解 C# 多线程详细讲解 一、基本概念 1、进程 首先打开任务管理器,查看当前运行的进程: 从任务管理器里面可以看到当前所有正在运行的进程。那么究竟什么是进程呢? 进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。 线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败 阅读详情

相关推荐

C# 多线程编程全面指南:从基础到高级实践

在现代软件开发中,多线程编程已成为提升应用程序性能的关键技术。C# 作为.NET平台的主力语言,提供了丰富的多线程处理机制。本文将全面介绍C#中的多线程编程技术,从基础概念到高级应用,帮助开发者掌握这一重要技能。

vvilkin的学习备忘 1438

C# 多线程并发编程基础

C# 中的线程是操作系统能够进行运算调度的最小单位,它被包含在进程中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程可以并发执行不同的任务。

butterfly_onfly的专栏 982

C# 多线程精通指南:从基础到高效并发编程的全面解析

多线程是指在同一程序中,同时执行多个线程的技术。每个线程代表一个独立的执行路径,可以并行处理不同的任务。多线程使得程序能够更好地利用现代多核处理器的性能,提升并行处理能力,减少等待时间。C# 通过命名空间提供了丰富的多线程支持,开发者可以轻松创建、管理和同步线程,从而使程序能够并行处理多个任务。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 994

C#多线程与异步编程:从基础到高级实践

C#的多线程编程:适用于CPU密集型任务,通过创建多个线程并行计算来提高性能。异步编程:适用于I/O密集型任务,能够在等待操作完成时不阻塞线程,提高程序的响应性。在实际应用中,我们往往需要将这两者结合使用,以充分利用多核处理器的能力和提高I/O操作的效率。通过深入理解并合理应用多线程与异步编程技术,开发者可以编写出高效、响应迅速的应用程序。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1374

c#多线程

总结一下同步方法和异步方法的区别:1、同步方法由于主线程忙于计算,所以会卡住界面。异步方法由于主线程执行完了,其他计算任务交给子线程去执行,所以不会卡住界面,用户体验性好。2、同步方法由于只有一个线程在计算,所以执行速度慢。异步方法由多个线程并发运算,所以执行速度快,但并不是线性增长的(资源可能不够)。多线程也不是越多越好,只有多个独立的任务同时运行,才能加快速度。3、同步方法是有序的。异步多线程是无序的:启动无序,执行时间不确定,所以结束也是无序的。

类人_猿的博客 3540

中国30米逐年植被净初级生产力(NPP)数据集(1982年至今CASA模型)

1.3 气温、降水、地表太阳辐射数据 气温和降水数据月度空间插值数据是基于全国2400多个站点的日观测数据,在计算各气象要素月值的基础上,基于Anusplin软件插值生成的1982年以来各月度30米分辨率气温和降水栅格数据,插值过程中引入高程作为协变量。气温单位为℃,降水单位为mm。1.2 土地覆盖数据 土地覆盖数据来源于1985 年-2020年全球30米精细地表覆盖动态监测产品,该数据集包含29个地表覆盖类型,进行拼接、裁剪、重分类和重采样处理,获得8期250米分辨率的植被类型数据。

地球资源数据云的官方博客 2839

商店销售预测(回归&随机森林)

通过准备线性回归的数据,我们发现了一些有趣的见解,包括周末的销售增长,公共部门支付工资时的销售增长,以及11月和12月的销售增长。如果我们选择包括这些,我们可能会得到更好的结果,但在这个时候,我们不会用它来做任何预测,而是将转向另一种可能给我们更好的结果的技术。在Kaggle竞赛中,要求我们应用时间序列预测,根据厄瓜多尔大型杂货零售商Corporación Favorita的数据预测商店销售情况,建立一个模型,准确地预测在不同商店销售的商品的单位销量。在快速查看我们的训练数据集之后,我们可以看到有很多零。

qq_45791012的博客 4750

Xilinx实战-深入AXI UART Lite IP核的配置与调试

本文详细介绍了Xilinx FPGA中AXI UART Lite IP核的配置与调试方法,包括Vivado环境下的IP核设置、关键参数优化、寄存器操作及常见问题排查。通过实战案例和代码示例,帮助开发者快速掌握AXI接口的串口通信技术,提升嵌入式系统开发效率。

weixin_29189377的博客 227

基于高精度三维机器视觉的新能源汽车锂电池表面缺陷检测

在机器视觉行业迅速发展的背景下,市场上提供了功能强大且种类齐全的3D相机系列,可以满足锂电池从电芯到模组各个工艺和工位的3D检测需求。

Hinyeung_Limited的博客 1132

【C++】POCO学习总结(六):线程、线程池、同步

Poco::RunnableAdapter继承自Poco::Runnable,在Poco::RunnableAdapter构造函数中指定了类和方法;Poco::ThreadLocal是线程局部变量,也叫线程局部存储,意思是模版ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。

郭老二 5099

【软件介绍】RVC本地部署使用方法

【摘要】RVC是一款功能强大的开源语音转换工具,具有实时处理、多音效选择、高质量音频处理等特点。文章详细介绍了RVC的安装与使用方法:1)配置Python环境;2)根据电脑系统选择对应安装包解压;3)启动程序进入浏览器操作界面。重点讲解了声音克隆的关键步骤:建议使用短音频素材,选择合适训练方法(推荐pm或rmvpe),设置100次训练轮数,生成的模型文件存入weights文件夹。最后通过上传音频即可实现声音克隆。操作过程需注意保持程序运行状态,并提供了相关资源下载地址。

心动的那一刻,记忆便盛开了花 2978

C# MES通信从入门到精通(1)——串口传输文件

本文详细介绍了在Mes通信领域如何使用串口发送文件,由实战经验总结,堪称MES通信领域的葵花宝典!

qq_34059233的博客 3750

华为OD机试 - 最佳对手(Python/JS/C/C++ 2025 A卷 200分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。游戏里面,队伍通过匹配实力相近的对手进行对战。但是如果匹配的队伍实力相差太大,对于双方游戏体验都不会太好。给定n个队伍的实力值,对其进行两两实力匹配,两支队伍实例差距在允许的最大差距d内,则可以匹配。要求在匹配队伍最多的情况下,匹配出的各组实力差

学Java,找哪吒 1379

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: C#中的多线程与线程死锁
下一篇: java中JVM和JMM之间的区别
普通网友
博客等级 码龄4年 3126粉丝 192原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值