C#多线程总结

本文详细介绍了C#中多线程的使用,包括异步线程的async和await关键字、基于委托的实现,同步线程,Thread、ThreadPool和Task线程的使用,线程生命周期,应用程序域,WinDbg工具的运用,以及多线程原理和资源管理。重点讲解了Task的多种使用方式和阻塞方式,以及如何处理异常和取消任务。此外,还探讨了多线程在跨线程访问控件和数据库等方面的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

一、异步线程

使用async和await关键字

基于委托实现

二、同步线程

三、Thread线程

开启线程

设置线程优先级

 Thread拓展封装

四、ThreadPool线程池

常规使用

设置线程数

线程等待

Thread和ThreadPool比较

通过线程池做一些扩展(定时器类)

五、Task线程(推荐使用)

 1、常规使用

new一个新的Task

Task.Run

Task.Factory

RunSynchronously

Parallel

2、Task中6种阻塞方式和任务延续

Join阻塞

 Delay延迟

Wait等待

WaitAll等待所有

WaitAny等待任一

ContinueWhenAll

ContinueWhenAny

3、TaskCreationOptions枚举

父子任务

长时间运行的任务处理

4、线程取消

抛出异常

CacellationTokenSoure

5、Task中的返回值获取

单任务返回结果

关联任务返回结果

多任务集中返回结果

6、Task中专门的异常处理AggregateException

7、多线程情况下的异常捕获

六、线程的生命周期

Start(开始)

Suspend(挂起)

Interrupt(中断)

Sleep(休眠)和Wait(等待)

Resume(恢复)

Abort(取消)

Join(阻塞)

ResetAbort(再次启用)

七、应用程序域

八、WinDbg的使用

九、多线程原理研究

线程在内存空间上的开销

线程在时间上的开销

十、多线程资源竞用问题

十一、Debug和Release区别

十二、应用场景

跨线程访问控件

跨线程访问数据库


前言

Q1:为什么要使用线程?

在多CPU和多核时代,使用线程能够充分利用硬件资源,提升软件的运行效率。但是没有章法的乱用线程会适得其反。

Q2:线程和进程关系?

一个程序运行,通常在任务管理器中看到一个进程。这个进程占用多少资源,并不是由进程本身决定。而是由这个进程分配 的线程决定。也就是说操作系统是通过线程来管理程序资源的。

一、异步线程

        异步线程是一种用于处理耗时操作的机制,它允许应用程序在执行某些操作时不被阻塞,以提高性能和响应性.

使用async和await关键字

using System;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main()
    {
        Console.WriteLine("开始执行异步操作");

        await ExecuteAsyncOperation(); // 调用异步方法,并在此等待其完成

        Console.WriteLine("异步操作完成");
    }

    public static async Task ExecuteAsyncOperation()
    {
        Console.WriteLine("开始执行异步操作");
        
        // 模拟一个耗时的操作,这里使用 Task.Delay 方法来模拟
        // 这个操作会暂停方法的执行,但不会阻塞主线程
        await Task.Delay(1000); // 暂停 1 秒钟
        
        Console.WriteLine("异步操作完成");
    }
}

基于委托实现

调用BeginInvoke()方法

利用返回结果状态做进度条

异步等待WaitOne

异步返回值EndInvoke

二、同步线程

        同步线程是指线程的执行是按照顺序的,每个操作都必须等待前一个操作完成后才能继续执行,这种线程模型被称为同步。

三、Thread线程

开启线程

设置线程优先级

thread.Priority=ThreadPriority.Highest;//设置高优先级,只是一个概率的提升

 Thread拓展封装

场景一:开启新线程执行任务后紧接着需要执行的一个任务

场景二:开启一个线程,既要不卡界面,又要返回结果

Func<int> func=()=>
{
	Thread.Sleep(2000);
	return 6;
};
Fun<int> funcResult=ThreadWithReturn(func);
int iResult=funcResult.Invoke();//如果需要执行结果,等待是必须的

四、ThreadPool线程池

线程池是一个用于管理和重用线程的机制,它提供了一种轻量级的方式来处理并发执行的任务。线程池在应用程序启动时会创建一组预分配的线程,这些线程被放置在线程池中,并准备好处理工作项。当应用程序需要执行某个任务时,可以将任务提交给线程池,并由线程池中的线程来执行任务。使用线程池的好处之一是可以减少线程创建和销毁的开销,因为线程池会重用已创建的线程,从而提高性能和资源利用率。

注:线程池是一个共享的资源,因此需要注意使用线程池的任务应尽量是短期的,以避免阻塞线程池中的其他任务。如果需要执行长时间运行的任务,可以考虑使用Async/Await或其他异步编程模型。

常规使用

1)ThreadPool.QueueUserWorkItem

运行结果:方法1、2中的任务是由线程池自动调度的

2)一些使用示例

设置线程数

线程等待

Thread和ThreadPool比较

【1】Thread:只要我们需要异步任务,都会开启一个Thread,比然有时间和空间开销。

【2】TheadPool:是一个线程池,由系统维护和缓存,因为默认都是初始化好的,所以使用方便,退回容易。用的时候,只需要请求即可。

Thread开启10个线程

ThreadPool开启10个线程

总结:

【1】我们的线程池可以根据电脑的实际CPU情况开启一定个数的线程,放到线程池中。

【2】10个异步任务,但是我们通过4个线程就完成了,节省时间和空间开销。

通过线程池做一些扩展(定时器类)

五、Task线程(推荐使用)

        Task是一种用于多线程编程的高级概念。Task可以把工作项分配给线程执行,使得你可以轻松地编写异步代码。

        在C# 5.0以前,编写异步代码需要使用回调函数或Thread类等底层API,这使得代码复杂难以维护。而在C# 5.0引入async/await语法之后,使用Task来编写异步代码变得更加简单和直观,使用Task来编写异步代码的好处之一是可以避免使用回调函数,使得代码更加简洁和易于维护。同时,Task还提供了其他高级的功能,如取消异步操作和处理多个异步操作的结果等。

 1、常规使用

new一个新的Task

例子

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值