• C#多线程和异步


    什么是线程

    线程是一个可执行的路径,他可以独立于其他线程执行。

    每个线程在操作系统的进程内执行,而操作系统提供了程序的运行独立环境。

    单线程指的是环境中跑了一个线程,所以该线程拥有独占权。

    多线程应用,单个进程中会跑多线程,他会共享当前执行环境。

    线程的一些属性

    线程一旦开始执行,isAlive就是true,线程结束就是false;

    线程结束的条件就是,线程构造函数传入委托结束了执行。

    线程一旦结束局无法重启。

    线程都有个name属性用来调试。

    静态的thread.currrentThread属性,会返回当前执行的线程。

    多线程目的是为了处理复杂耗时的工作,设置不同的线程处理不同的工作是能提高效率的方法。

    线程生命周期:起始(System.Threading.Thread类被创建),结束(线程被终止)。

    生命周期中的状态:

    1.创建但为使用:创建好了线程但没使用start调用。

    2.就绪状态:当线程准备好运行等待CPU周期状态

    3.不可运行状态:①调用sleep。②调用了wait。③I/O阻塞。

    4.死亡状态:线程执行完毕关闭了。

    主线程:C#在执行的时候第一个线程就是主线程,也是自动创建的。

    public static void CallToChildThread()
    {
        try
        {
    
            Console.WriteLine("Child thread starts");
            // 计数到 10
            for (int counter = 0; counter <= 10; counter++)
            {
                Thread.Sleep(500);
                Console.WriteLine(counter);
            }
            Console.WriteLine("Child Thread Completed");
    
        }
        catch (ThreadAbortException e)
        {
            Console.WriteLine("Thread Abort Exception");
        }
        finally
        {
            Console.WriteLine("Couldn't catch the Thread Exception");
        }
    
    }
    static void Main()
    {
        ThreadStart childref = new ThreadStart(CallToChildThread);
        Console.WriteLine("In Main: Creating the Child thread");
        Thread childThread = new Thread(childref);
        childThread.Start();
        // 停止主线程一段时间
        Thread.Sleep(2000);
        // 现在中止子线程
        Console.WriteLine("In Main: Aborting the Child thread");
        childThread.Abort();
    }

    这里只是线程的体现,一般不会这样使用。

     Join and sleep

    调用join方法,就可以等待另一个线程的结束。

    调用join的时候,可以设置一个超时,使用毫秒或者TimeSpan。

    调用sleep就是等待

    注意:Thread.Sleep(0)这样调用会导致线程放弃本身的时间片,自动将cpu移交给其他线程。

    阻塞:如果线程的执行由于什么原因导致暂停,就是线程阻塞了。

    被阻塞的线程会立即将处理器的时间片交个其他线程,从此就不在消耗处理器的时间,直到满足阻塞条件。

     可以通过ThreadState这个竖向判断线程是否被阻塞

    bool blocked=(someThread.ThreadState & ThreadState.waitSleepJion)!=0

    ThreadState 属性的取值如下:

    Aborted:线程已停止;

    AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;

    Background:线程在后台执行,与属性Thread.IsBackground有关;

    Running:线程正在正常运行;

    Stopped:线程已经被停止;

    StopRequested:线程正在被要求停止;

    Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);

    SuspendRequested:线程正在要求被挂起,但是未来得及响应;

    Unstarted:未调用Thread.Start()开始线程的运行;

    WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;

    解除阻塞:

    但遇到下面四种情况才解除阻塞

    1.阻塞条件满足

    2.操作超时

    3.通过Thread.Interrupt()进行打断

    4.通过Thread.Abort()进行中止

    IO-bound和Compute-bound

    一个话费大量时间去等待某件事发生叫做IO-bound

    IO-bound绑定操作通常涉及输入输出,但不是硬性要求,Thread.Sleep()也被叫做IO-bound

    IO-bound也可以是干等这,什么也不干

    相反,话费大量时间执行cpu密集工作的叫做Compute-Bound

    compute-bound就是指的很忙,没时间

    阻塞和忙等待:Blocking and Spinning

    IO-bound操作工作方式有两种:

      在当前线程上同步等待:Console.ReadLine(),Thread.sleep(),

    异步操作,稍后操作完等待回调

    忙等待:while(DateTime.Now<nextStartTime);

    忙等待和阻塞有些差别:

    希望时间短,就考虑忙等待.net framework 提供了特殊的方法SpinLock和SpinWait

    其次,阻塞线程成本比较高,会带来额外开销(上下文切换,会有2微秒)

    因此,处理大量的IO-bound,阻塞很麻烦,所以需要基于回调,等待时期撤销线程。

    本地VS共享状态

    CLR为每个线程分配了自己的内存占(stack),以便本地变量保持独立

    共享:

    如果多个线程都引用同一个对象实例,那么就共享数据

    被lambda表达式活匿名委托捕获的变量,也是公用的

    静态字段

  • 相关阅读:
    leetCode 78.Subsets (子集) 解题思路和方法
    大话设计模式C++版——代理模式
    不用加减乘除做加法
    hdu 1257
    小学生算术
    字符串排序问题
    POJ 2421 Constructing Roads
    http://vdceye.com/ 全新页面上线
    POJ3262 Protecting the Flowers 【贪心】
    集群环境下JSP中获取客户端IP地址的方法
  • 原文地址:https://www.cnblogs.com/liuyang95/p/11655380.html
Copyright © 2020-2023  润新知