• C#秘密武器之多线程——基础


     多线程概述

    什么是进程?

          当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。

    什么是线程?

          线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

    什么是多线程?

         多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

    多线程的好处

          可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。

    多线程的不利方面

         线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 多线程需要协调和管理,所以需要CPU时间跟踪线程; 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;线程太多会导致控制太复杂,最终可能造成很多Bug;

    .NET中的多线程

    一、创建线程

    我们可以使用Thread类的构造函数创建线程,用无参数的TheadStart委托或者带有一个参数的ParameterizedTheadStart委托作为构造函数的参数即可。线程执行其实就是执行里边的线程函数——即里边的委托函数!

    public delegate void ThreadStart();  
    public delegate void ParameterizedThreadStart(object obj);

    举个栗子:

    static void Main()  
    {  
        Thread t = new Thread(new TheadStart(Go));
        //Thread t = new Thead(Go);
        t.Start();  
    }  
    static void Go()  
    {  
        Console.Write("hello!");  
    }  
    
    static void Main()  
    {  
        Thread t = new Thread(Go);  
        t.Start("hello");  
        Go();  
    }  
    static void Go(object msg)  
    {  
        string message = (string)msg;  
        Console.Write(message);  
    }  

    二、启动线程

    start():将当前线程的状态更改为 ThreadState.Running。

    一旦线程处于 ThreadState.Running 状态,操作系统就可以安排其执行。 线程从方法的第一行(由提供给线程构造函数的 ThreadStart 或 ParameterizedThreadStart 委托表示)开始执行。线程一旦终止,它就无法通过再次调用 Start 来重新启动。

    三、线程睡眠

    Thread.Sleep(int ms);
    Thread.Sleep(TimeSpan timeout);

    上述方法为Thread类的两个静态方法,用来阻止当前线程指定的时间。

    四、终止线程

    使用Abort方法实现,用于永久地停止托管线程。一旦线程被中止,它将无法重新启动。Abort会引发ThreadAbortException异常,同时可以传递一个终止的参数信息。

    Thread.Abort();
    Thread.Abort(Object  stateInfo);

    注意:Suspend和Resume为废弃方法,不要使用!

    五、线程属性

    5.1、线程名字

    每个线程都有一个Name属性,可以设置和修改,但是只能设置一次。

    5.2、后台线程

    在.net中线程分为前台线程和后台线程,在一个进程中,当所有前台线程停止运行时,CLR会强制结束仍在运行的任何后台线程,这些后台线程直接被终止,不会抛出异常。所以我们应该在前台线程中执行我们确实要完成的事情!

    static void Main(string[] args)
    {
        Thread t = new Thread(Test);
        t.IsBackground = true;
        //这里线程是后台线程,应用程序马上结束
        //假如是前台线程,大约5秒以后结束
        t.Start();
        Console.WriteLine("A");
    }
    static void Test()
    {
        Thread.Sleep(5 * 1000);
        Console.WriteLine("B");
    }

    5.3、线程优先级

    线程的优先级使用Priority设置或获取,只有在运行时才有作用,分为5个级别:

    enum ThreadPriority{Lowest, BelowNormal , Normal, AboveNormal, Highest}

    举个栗子:

    myThread.Priority=ThreadPriority.Lowest;

    注意:优先等级高的线程占用更多的CUP时间。 但是当优先等级高的线程正在等待一些资源的时候,优先等级低的线程可以运行。

    六、阻塞线程

    阻塞某个线程用的方法是join()。这个方法可以让并发处理变得串行化,让主线程去等待某个线程执行完毕才继续往下执行!

    class Test
    {
        static void Main()
        {
            Thread t = new Thread(Run);
    
            t.Start();
    
            //Join相当于把Run方法内嵌如此
            t.Join();
    
            //该死的t.Join(),害的我主线程必须在你执行完后才能执行。
            Console.WriteLine("我是主线程:" + Thread.CurrentThread.GetHashCode());
        }
    
        static void Run()
        {
            //等待5s
            Thread.Sleep(5000);
    
            Console.WriteLine("我是线程:" + Thread.CurrentThread.GetHashCode());
        }
    }

    七、线程的异常处理

    线程的异常都是在线程函数里边解决的,因此应该把try catch放在线程的委托函数里边~

    static void Main(string[] args)  
    {  
        try  
        {  
            new Thread(Go).Start();  
        }  
        catch (Exception ex)  
        {  
            Console.Write(ex.Message);  
        }  
          
        Console.ReadKey();  
    }  
    static void Go()  
    {  
        try  
       {  
              ///处理逻辑  
        }
       catch(Exception e)
        {  
              Console.Write(e.Message);  
        }  
    }  

    注意:在调用Abort方法终止一个线程时,在异常处理的时候为了防止程序再次抛出异常,在catch里边处理完异常之后最好加上Thread.ResetAbort();这条语句!

  • 相关阅读:
    js float浮点数计算精度问题
    NLB多WEB站点访问共享文件解决方案
    Flash文件跨域访问
    博客地址
    在Ubuntu上安装Mysql
    Ajax调用NPOI导出Excel报表
    在Ubuntu上安装Mongodb
    获取月份的周时间段
    sql表结构和注释
    Highcharts使用指南
  • 原文地址:https://www.cnblogs.com/WeiGe/p/4237815.html
Copyright © 2020-2023  润新知