多线程编程

来源:互联网 发布:ubuntu 端口流量 编辑:程序博客网 时间:2024/05/17 06:41

进程是程序在内存中的实例,一个进程中可以包含多个线程,线程间的切换速度比进程间的切换速度快,所以在处理多任务的时候,多线程开发显然是首选。

线程只拥有寄存器和内存堆栈,并且只可以使用进程获得的资源。

线程的创建使用的是ThreadStart()这个委托函数,方法原型: 启动调用.Start()方法,由于单核CPU在同一时间内CPU只能处理一条CPU指令,多线程编程实现的并发,实际上是操作系统为cpu分配的时间片轮转,在各个线程间切换。实现了宏观上并行,微观上穿行。进程初始化时,会自动创建一个新线程,为主线程,当主线程执行过程中,自行定义新的线程,为子线程。子线程的生命周期为子线程函数结束。.NET线程执行默认是非阻塞模式,子线程.Start()启动后,并不会立即执行,而是等待主线程时间片结束后,才开始执行子线程。然后:  子线程->主线程->子线程->主线程 。。。 来回切换执行,直到线程生命周期结束。在这个过程中,如果主线程先于子线程结束,那么子线程仍在执行(除非应用程序主动关闭,这时就是强行结束进程,会收回资源,所有线程也就相应结束。),CLR要等到子线程运行结束后,才会结束整个进程。在这个过程中,我们可以调用.Abort()方法来强行结束子线程,这样做的缺点就是会造成资源(文件句柄)的无法回收。.Abort()的调用,会引发一个ThreadAbortException的异常,我们可以在子线程里捕捉到这个异常,并在进行相应的处理,并在finally块中进行资源回收。

线程在创建时,可以设置其Background属性为True(默认是False),该线程就为背景线程,背景线程的含义就是,一旦主线程结束,背景线程就立即结束。倘若在线程创建时,需要等待新创建线程先执行完毕后,再继续执行主线程,则可对子线程调用.Start()方法后再调用.Join()方法,则主线程在该处阻塞,等待子线程生命周期结束后,才继续运行。

使用多线程编程时,最麻烦的就是创建线程时无法传参,也无法有返回值。因为委托ThreadStart()是参数,无返回值类型的。如果需要传参进去,就需要调用另一个委托函数去初始化子线程,ParameterizedThreadStart(),方法原型: ,可以看出,该委托传入的参数是一个Object类型,那么线程的构造函数的参数形式就应该是(Object obj)

 

如果要在子线程中得到返回值,但线程的委托方法是不允许有返回值的。这时候我们就需要构造一个暂存数据的类。在子线程执行的过程中,将数据暂时保存到类的属性中。

 

这样,我们在结束的时候,可以调用obj.returnValue,来获取返回值。不过这样在额外创建一个子线程时,没有错,但在多线程并发时,多线程同时访问临界区(共有程序段),就会导致属性值的混乱。所以在多线程时,还有线程同步问题。

原创粉丝点击