首页 > 技术文章 > .net 多线程

wangqiang3311 2018-03-08 18:08 原文

一、概念

         什么是线程?线程是程序执行最基本单元,它是一种数据结构。

         百度百科是这样描述的:

         线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。

         维基百科是这样定义的:

        In computer science, a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.[1] The implementation of threads and processes differs between operating systems, but in most cases a thread is a component of a process. Multiple threads can exist within one process, executing concurrently and sharing resources such as memory, while different processes do not share these resources. In particular, the threads of a process share its executable code and the values of its variables at any given time.

       在计算机科学当中,线程是操作系统能够进行调度的最小单位。每个操作系统的线程和进程的实现有所不同,但是大多情况下,线程是进程的一个组件。一个进程中可以有许多线程共存,可并发执行以及共享资源(如内存),而不同进程间不会共享资源,尤其多线程在任何时候可以共享可执行代码,变量值。

       什么是进程?进程是运行中的程序,拥有系统分配的资源。

       百度百科的定义:

       进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

       维基百科的定义:

        In computing, a process is an instance of a computer program that is being executed. It contains the program code and its current activity. Depending on the operating system (OS), a process may be made up of multiple threads of execution that execute instructions concurrently.[1][2]

       在计算机中,进程是计算机程序执行的实例。它包含程序代码以及当前的活动。依赖于操作系统,一个进程是由多个并行,可执行线程组成的。

二、线程的分类

      

 

三、线程的状态

    

 四、.net中如何开启一个线程

      1、直接new一个Thread,默认是前台线程。由于线程代表了某一类方法的运行,所以得用到委托。我们先看看Thread的构造函数:

public Thread(ParameterizedThreadStart start)
        {
            if (start == null)
            {
                throw new ArgumentNullException("start");
            }
            this.SetStartHelper(start, 0);
        }
        
        public Thread(ThreadStart start)
        {
            if (start == null)
            {
                throw new ArgumentNullException("start");
            }
            this.SetStartHelper(start, 0);
        }

我们看到Thread构造函数接收 ThreadStart和ParameterizedThreadStart类型的start。那么分别看它们是什么类型:

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

原来一个是带参数的委托,另一个是不带参数的委托。

 2、定义一个Timer

       public Timer(TimerCallback callback)
        {
            int num = -1;
            int num2 = -1;
            StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
            this.TimerSetup(callback, this, (uint) num, (uint) num2, ref lookForMyCaller);
        }

        public Timer(TimerCallback callback, object state, int dueTime, int period)
        {
            if (dueTime < -1)
            {
                throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            }
            if (period < -1)
            {
                throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
            }
            StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
            this.TimerSetup(callback, state, (uint) dueTime, (uint) period, ref lookForMyCaller);
        }

 

System.Threading.Timer,构造函数接收 TimerCallback 类型,我们看下此类型的定义:

 public delegate void TimerCallback(object state);

原来是可以传参的委托。

 3、从线程池中取出的线程

     ThreadPool.QueueUserWorkItem

     New Task

 public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable

 从Task类的定义看,它实现了线程池工作者接口,实现了异步。

 public Task(Action action, System.Threading.CancellationToken cancellationToken) : this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
        {
            StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;
            this.PossiblyCaptureContext(ref lookForMyCaller);
        }

这是它众多构造函数中一个,接收Action类型的委托,cancellationToken为协作式取消线程执行的一个对象。

Task.Factory.StartNew
Task.Run

   Task功能非常强大,可参考其它文章理解。

  五、多线程的异步

        异步处理的三个步骤:

            1、启动处理   2、实际处理(比较耗时)   3、任务完成后的处理

            第一步由主线程完成,第二步由子线程完成,第三步如果由主线程完成,那么就牵扯到主线程和子线程之间的同步问题,因为主线程要获取子线程执行的结果,以便完成第三步。如果第三步由子线程完成,那么就可避免这个问题,因为第二步和第三步都由子线程完成,它们是由同一个线程来处理的。

           异步处理需要IAsyncResult,无论是事件,还是委托的Begin、End方法,都是基于IAsyncResult实现的。

  六、多线程的同步

          同步牵扯到对系统资源的竞争或者线程间需要协作完成某些任务。可参考我的其它文章。

推荐阅读