C#多线程(1)

一、基本概念

1、进程

首先打开任务管理器,查看当前运行的进程:

从任务管理器里面可以看到当前所有正在运行的进程。那么究竟什么是进程呢?

进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。

二、线程

在任务管理器里面查询当前总共运行的线程数:

线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。

二、多线程

2.1 多线程的优点

①可以同时完成多个任务;

②可以使程序的响应速度更快;

③可以让占用大量处理时间的任务或当前没有进行处理的任务定期将处理时间让给别的任务;

④可以随时停止任务;可以设置每个任务的优先级以优化程序性能。

那么可能有人会问:为什么可以多线程执行呢?总结起来有下面两方面的原因

1、CPU运行速度太快,硬件处理速度跟不上,所以操作系统进行分时间片管理。这样,从宏观角度来说是多线程并发的,因为CPU速度太快,察觉不到,看起来是同一时刻执行了不同的操作。但是从微观角度来讲,同一时刻只能有一个线程在处理。

2、目前电脑都是多核多CPU的,一个CPU在同一时刻只能运行一个线程,但是多个CPU在同一时刻就可以运行多个线程。

然而,多线程虽然有很多优点,但是也必须认识到多线程可能存在影响系统性能的不利方面,才能正确使用线程。不利方面主要(缺点)有如下几点:

①线程也是程序,所以线程需要占用内存,线程越多,占用内存也越多。

②多线程需要协调和管理,所以需要占用CPU时间以便跟踪线程。

③线程之间对共享资源的访问会相互影响,必须解决争用共享资源的问题。

④线程太多会导致控制太复杂,最终可能造成很多程序缺陷。

当启动一个可执行程序时,将创建一个主线程。在默认的情况下,C#程序具有一个线程,此线程执行程序中以Main方法开始和结束的代码,Main()方法直接或间接执行的每一个命令都有默认线程(主线程)执行,当Main()方法返回时此线程也将终止。

一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。在C#中,线程是使用Thread类处理的,该类在System.Threading命名空间中。使用Thread类创建线程时,只需要提供线程入口,线程入口告诉程序让这个线程做什么。通过实例化一个Thread类的对象就可以创建一个线程。创建新的Thread对象时,将创建新的托管线程。Thread类接收一个ThreadStart委托或ParameterizedThreadStart委托的构造函数,该委托包装了调用Start方法时由新线程调用的方法,示例代码如下:

Thread thread=new Thread(new ThreadStart(method));//创建线程

thread.Start();                                                           //启动线程

上面代码实例化了一个Thread对象,并指明将要调用的方法method(),然后启动线程。ThreadStart委托中作为参数的方法不需要参数,并且没有返回值。ParameterizedThreadStart委托一个对象作为参数,利用这个参数可以很方便地向线程传递参数,示例代码如下:

Thread thread=new Thread(new ParameterizedThreadStart(method));//创建线程

thread.Start(3);                                                                             //启动线程

2.2 创建多线程的步骤:
1、编写线程所要执行的方法
2、实例化Thread类,并传入一个指向线程所要执行方法的委托。(这时线程已经产生,但还没有运行)
3、调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定

2.3 System.Threading.Thread类

Thread类是是控制线程的基础类,位于System.Threading命名空间下,具有4个重载的构造函数:

名称 说明
Thread(ParameterizedThreadStart)

初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。要执行的方法是有参的。

Thread(ParameterizedThreadStart, Int32) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈大小
Thread(ThreadStart)

初始化 Thread 类的新实例。要执行的方法是无参的。

Thread(ThreadStart, Int32)

初始化 Thread 类的新实例,指定线程的最大堆栈大小。

2.3.1 ThreadStart是一个无参的、返回值为void的委托。委托定义如下:

public delegate void ThreadStart()

①通过ThreadStart委托创建并运行一个线程:

using System;
using System.Threading;

namespace Study_ThreadDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建无参的线程
            Thread thread1 = new Thread(new ThreadStart(NoParameterMethod));
            //调用Start方法执行
            thread1.Start();

            Console.ReadKey();

        }

        //创建无参的静态方法
        static void NoParameterMethod()
        {
            Console.WriteLine("这是一个无参数的方法!!!");
        }


    }//Class_end
}

运行结果如下: 

 

②除了可以运行静态的方法,还可以运行实例方法 

using System;
using System.Threading;

namespace Study_ThreadDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //实例化类
            TestMethod testMethod = new TestMethod();

            //创建无参的线程
            Thread thread1 = new Thread(new ThreadStart(testMethod.MyThread));
            //调用Start方法执行
            thread1.Start();

            Console.ReadKey();

        }

        //创建无参的方法
        static void NoParameterMethod()
        {
            Console.WriteLine("这是一个无参数的方法!!!");
        }


    }//Class_end

    class TestMethod
    {
        //构造函数
        public TestMethod()
        {
            Console.WriteLine("这是该类的构造函数进行初始化!!!");
        }

        public void MyThread()
        {
            Console.WriteLine("这是一个实例化的方法!!!");
        }
    }
        



}

运行结果如下所示:

 

③如果为了简单,也可以通过匿名委托或Lambda表达式来为Thread的构造方法赋值 

using System;
using System.Threading;

namespace Study_ThreadDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //1、通过匿名委托创建
            Thread thread1 = new Thread(delegate () { Console.WriteLine("我是通过匿名委托创建的线程!!!"); });
            //调用Start方法执行
            thread1.Start();

            //2、通过Lambda表达式创建
            Thread thread2 = new Thread(()=> { Console.WriteLine("我是通过Lambda表达式创建的委托"); });
            thread2.Start();

            Console.ReadKey();

        }

    }//Class_end


}

运行结果如下所示:

 

2.3.2  ParameterizedThreadStart是一个有参的、返回值为void的委托,定义如下:

public delegate void ParameterizedThreadStart(Object obj)

using System;
using System.Threading;

namespace Study_ThreadDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //通过ParameterizedThreadStart创建线程
            Thread thread1 = new Thread(new ParameterizedThreadStart(showInfo));
            //给方法传递值
            thread1.Start("这是一个有参数的委托!");

            Console.ReadKey();

        }

        /// <summary>
        /// 创建有参数的方法
        /// 注意:方法里面的参数类型必须为Object类型
        /// </summary>
        /// <param name="info"></param>
        static void showInfo(object info)
        {
            Console.WriteLine("当前输出的内容="+info);
        }


    }//Class_end


}

运行结果如下所示:

注意:ParameterizedThreadStart委托的参数类型必须是Object的。如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null。

 

注意:本文内容来自https://www.cnblogs.com/dotnet261010/p/6159984.html

猜你喜欢

转载自blog.csdn.net/xiaochenXIHUA/article/details/89337392