C#多线程开发实战记录之线程基础

目录
  • 前言
  • 线程基础
    • 1、创建线程
    • 2、暂停线程
    • 3、线程等待
    • 4、线程终止
    • C#中的lock关键字
  • 总结

前言

最近由于工作的需要,一直在使用C#的多线程进行开发,其中也遇到了很多问题,但也都解决了。后来发觉自己对于线程的知识和运用不是很熟悉,所以将利用几篇文章来系统性的学习汇总下C#中的多线程开发。

线程基础

进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元” 这句话应该学习计算机的朋友或多或少都听说过,这在操作系统这门课中是很重要的一个概念。

在操作系统中可以同时运行很多个应用程序,那么你知道计算机是如何分配和调度这些应用程序去使用CPU进行工作的吗?

这里面就牵扯到了进程、线程的概念,也就是我们接下来要学习的内容。

一个应用程序会有很多个线程,但是只能有一个进程。也就是说一个进程中可以有很多个线程。那么这是为什么呢?以前计算机只有一个计算模块,每次只能单一的执行一个计算单元,不能同时执行多个计算任务。现在随着科技的发展,有了多核CPU,可以一次性执行多个应用程序,这样就实现了多任务。操作系统为了不让一个应用程序独占CPU,导致其余程序挂起等待,不得不设计出一种将物理计算单元分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力。此外,操作系统必须始终能够优先访问CPU,并能调整不同程序访问CPU的优先级(说白了就是典型的以空间换时间)。

线程正是这一概念的实现,可以认为线程是一个虚拟的进程,用于独立运行一个特定的程序。

大量使用线程会消耗大量的OS资源

那么为什么需要使用线程呢!其实就是为了在相同的时间内,让操作系统或CPU干更多的活,那么在C#中线程应该如何使用或者说在什么场景下使用呢!

在C#中关于线程的使用,大多数时候是在当程序需要处理大量繁琐、占用资源多、花费大量时间的任务时进行应用,比如访问数据库,视频显示,文件IO操作、网络传输等。

线程在应用程序中可以进行如何操作:1、创建线程;2、暂停线程;3、线程等待;4、终止线程。

1、创建线程

通过声明并实例化Thread就可以创建线程,它接收方法作为参数。使用Thread.Start()就可以开启子线程,让其去执行方法中的内容。

        static void Main(string[] args)
        {
            //新创建的线程中输出
            Thread oneThread = new Thread(PrintNumber);
            oneThread.Start();

            //主线程中输出
            PrintNumber();
            Console.ReadKey();
        }

        static void PrintNumber()
        {
            Console.WriteLine("开始......");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i);
            }
        }

可以看到当我们在子线程和主线程中同时输出PrintNumber()中的内容时,它是乱的随机交叉输出的。

2、暂停线程

暂停线程故名思意就是让线程暂停,不让其占用CPU资源,在一直等待,啥时候取消暂停就恢复运行。在C#中暂停就是让这个线程进入睡眠状态,让其休眠,不让其占用系统资源就可以了。

  Thread.Sleep(TimeSpan.FromSeconds(2));    //睡眠2s

3、线程等待

线程等待就是多个线程在处理某个任务时,某个线程必须等待前一个线程处理所有数据后才可以进行执行,在这个期间,这个线程是阻塞状态的。只有前一个线程完事了,他才可以再继续执行。

        static void Main(string[] args)
        {
            //新创建的线程中输出
            Thread oneThread = new Thread(PrintNumber);
            oneThread.Start();
            oneThread.Join();

            //主线程中输出
            PrintNumber();
            Console.ReadKey();
        }

也就是说上面的程序主线程必须得等oneThread线程执行完PrintNumber方法后,它才可以执行。

4、线程终止

就是线程在执行过程中,利用某些操作(Thread.Abort())可以使其线程立即退出,不进行工作了。

        static void Main(string[] args)
        {
            //新创建的线程中输出
            Thread oneThread = new Thread(PrintNumber);
            oneThread.Start();

            Thread.Sleep(TimeSpan.FromSeconds(6));
            oneThread.Abort();

            //主线程中输出
            PrintNumber();
            Console.ReadKey();
        }

上面的程序可以看到,当主程序再等待6s后,立即将oneThread线程终止掉。

其实Abort()方法是给线程注入了ThreadAbortException方法,导致线程被终结,这其实很危险,因为该线程可能正在处理某些重要的数据,比如接收传输数据等,这样子就传递摧毁了程序,数据也就丢失了。还有就是这个方法不能保证100%终止线程。有时候有些异常会被吃掉,我们可以利用某些关键变量在子线程中进行控制,从而取消线程的执行就可以。

在实际编码使用线程的过程中,可以通过oneThread.ThreadState来获取目前线程的状态。有时候我们也可以手动的设置线程的优先级,设置为最高的则提前执行,但是这个只是针对于单核CPU时,目前市面上基本都是多核的了,这种使用场景也就很少了。

一般我们创建的线程都是属于前台线程,通过手动设置ontThread对象的IsBackground属性为true时才会为后台线程。通常前台线程会比后台线程提前执行完。当前台线程执行完成后,程序结束并且后台线程被终结。进程会等待所有的前台线程完成后再结束工作,但是如果只剩下后台线程,进程会直接结束工作。

C#中的lock关键字

某一个资源当被多个线程同时访问时,可能这个资源的某些值对于各个线程来说会出问题。如果在某一时刻,一个线程是使其递增,一个线程是递减,会导致其值不唯一,各个线程拿到的值不对。这种情况就是所谓的竞争条件,竞争条件是多线程环境中非常常见的导致错误的原因。

    class PepoleCount
    {
        int count = 0;
        public void AddCount()
        {
            ++count;
        }
        public void DeleteCount()
        {
            --count;
        }
    }

比如是上面的程序,当两个线程同时访问这个PepoleCount类时,会导致count变量出现竞争条件。就是每个线程可能拿到的数值不是最新的。那么如何办呢,此时就需要使用到lock机制,也就是加锁。目的是为了当一个线程访问某个资源时,其余线程如果在访问时,必须等待当前访问完事后,它才可以访问。保证了数据的有效性。

lock关键字是如果锁定了一个对象,需要访问该对象的所有其他线程则会处于阻塞状态,并等待知道该对象解除锁定才可以访问。

    class PepoleCount
    {
        private readonly object _syncRoot = new object();
        int count = 0;
        public void AddCount()
        {
            lock(_syncRoot)
            {
                ++count;
            }
        }
        public void DeleteCount()
        {
            lock(_syncRoot)
            {
            --count;
            }
        }
    }

关于加锁这块还是有很多讲究的,不是说每一个方法,每一个变量都需要进行加锁,如果频繁的加锁会导致其余线程处于阻塞状态,那么也会导致应用程序出现严重的性能问题。

总结

到此这篇关于C#多线程开发实战记录之线程基础的文章就介绍到这了,更多相关C#多线程基础内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c#多线程编程基础

    无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应用户操作,同时在用户事件之间或者甚至在用户事件期间利用处理器,最强大的方式之一是使用多线程技术. 多线程:线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.如果某个线程进行一次长延迟操作, 处理器就切换到另一个线程执行.这样,多个线程的并行(并发)执行隐藏了长延迟,提高了处理器资源利用率

  • c#中多线程访问winform控件的若干问题小结

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来解决这个问题,下面我将详细的介绍. 首先来看传统方法: 复制代码 代码如下: public partial class Form1 : Form     {        public Form1()        {            InitializeComponent();        } private void Form1_Load(object sender,

  • C#实现多线程写入同一个文件的方法

    本文实例讲述了C#实现多线程写入同一个文件的方法.分享给大家供大家参考.具体实现方法如下: namespace WfpApp { public partial class Form2 : Form { object obj = new object(); public Form2() { InitializeComponent(); System.Threading.Thread thread; string[] users = new string[] { "zkk", "

  • C# 多线程编程技术基础知识入门

    什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数. 什么是多线程? 多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务. 多线程是指程序中包含多个执行流,即在一个程序中

  • c# winform多线程的小例子

    在文本框中输入一个数字,点击开始累加按钮,程序计算从1开始累计到该数字的结果.因为该累加过程比较耗时,如果直接在UI线程中进行,那么当前窗口将出现假死.为了有更好的用户体验,程序启动一个新的线程来单独执行该计算,然后每隔200毫秒读取一次累加结果,并把结果显示到文本框下方的label控件中.同时,程序支持取消操作,点击取消累计按钮,程序将取消累加操作,并把当前累加值显示到label中.为了方便后面的描述,我把UI线程称作主线程,把执行累加计算的线程称作工作者线程.该过程有两个关键点: 1:如何在

  • C#队列Queue多线程用法实例

    本文实例讲述了C#队列Queue多线程用法.分享给大家供大家参考.具体分析如下: 这里展示一个例子,供学习使用: private void button_测试Queue结合多线程_Click(object sender, EventArgs e) { Console.WriteLine("初始化队列"); queue = new Queue<string>(); string[] cars = new string[]{"宝马","奔驰&quo

  • 浅解关于C#多线程的介绍

    多线程的相关概念--------------------------------------------------------------------------------1.进程:是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体:由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元.2.线程:线程是程序中一个单一的顺序控制流程.是程序执行流的最小单元.另外,线程是进程中的一个实体,是被系统独立调度和分派的基本

  • c#使用多线程的几种方式示例详解

    (1)不需要传递参数,也不需要返回参数 ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值. 复制代码 代码如下: class Program { static void Main(string[] args) { for (int i = 0; i < 30; i++) { ThreadStart threadStart = new ThreadStart(Calculate); Thread thread = new Thread(thr

  • C#多线程基础知识汇总

    最近自己写了个小爬虫,里面用到了多线程技术,忽然发现对此技术竟然有些陌生了,于是乎开始疯狂的去问度娘,在此记录下来,以便自己和各位小伙伴们学习. 一.什么是线程 一个应用程序就相当于一个进程,进程拥有应用程序的所有资源进程包括线程,进程的资源被线程共享,但不拥有线程.我们可以打开电脑中的任务管理器,运行的.exe都是一个进程,里面的分支是线程. 二.多线程 多线程其实就是进程中一段并行运行的代码 1. 创建并启动线程 static void Main() { //获取线程Id var threa

  • c#多线程中Lock()关键字的用法小结

    本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生. 其中,lock是一种比较好用的简单的线程同步方式,它是通过为给定对象获取互斥锁来实现同步的.它可以保证当一个线程在关键

随机推荐