为什么使用多线程? 异步操作

来源:互联网 发布:视频特技制作软件 编辑:程序博客网 时间:2024/03/29 02:13

C#是一门支持多线程的语言,因此线程的使用也是比较常见的。由于线程的知识在Win32编程的时候已经说得过多,所以在.Net中很少介绍这部分(可能.Net不觉得这部分是它所特有的)。

 

那么线程相关的问题大致有如下四类(这篇文章只讨论单线程、单线程与UI线程这两方面的问题)。

问题一,线程的基本操作,例如:暂停、继续、停止等;

问题二,如何向线程传递参数或者从中得到其返回值;

问题三,如何使线程所占用的CPU不要老是百分之百;

最后一个,也是问题最多的,就是如何在子线程来控制UI中的控件,换句话说,就是在线程中控制窗体某些控件的显示。

 

对于问题一,我不建议使用Thread类提供的SuspendResume以及Abort这三个方法,前两个有问题,好像在VS05已经屏蔽这两个方法;对于Abort来说,除了资源没有得到及时释放外,有时候会出现异常。如何做呢,通过设置开关变量来完成。

 

对于问题二,我不建议使用静态成员来完成,仅仅为了线程而破坏类的封装有些得不偿失。那如何做呢,通过创建单独的线程类来完成。

 

对于问题三来说,造成这个原因是由于线程中进行不间断的循环操作,从而使CPU完全被子线程占有。那么处理此类问题,其实很简单,在适当的位置调用Thread.Sleep(20)来释放所占有CPU资源,不要小看这20毫秒的睡眠,它的作用可是巨大的,可以使其他线程得到CPU资源,从而使你的CPU使用效率降下来。




在子线程中操纵UI线程中的对象

http://blog.csdn.net/knight94/archive/2006/03/16/626584.aspx

http://blog.csdn.net/knight94/archive/2006/05/27/757351.aspx

 

首先说说,为什么不能直接在子线程中操纵UI呢。原因在于子线程和UI线程属于不同的上下文,换句比较通俗的话说,就好比两个人在不同的房间里一样,那么要你直接操作另一个房间里的东西,恐怕不行罢,那么对于子线程来说也一样,不能直接操作UI线程中的对象。

 

那么如何在子线程中操纵UI线程中的对象呢,.Net提供了InvokeBeginInvoke这两种方法。简单地说,就是子线程发消息让UI线程来完成相应的操作。

 

这两个方法有什么区别,这在我以前的文章已经说过了,Invoke需要等到所调函数的返回,而BeginInvoke则不需要。

 

用这两个方法需要注意的,有如下三点:

第一个是由于InvokeBeginInvoke属于Control类型的成员方法,因此调用的时候,需要得到Control类型的对象才能触发,也就是说你要触发窗体做什么操作或者窗体上某个控件做什么操作,需要把窗体对象或者控件对象传递到线程中。

 

第二个,对于InvokeBeginInvoke接受的参数属于一个delegate类型,我在以前的文章中使用的是MethodInvoker,这是.Net自带的一个delegate类型,而并不意味着在使用Invoke或者BeginInvoke的时候只能用它。参看我给的第二篇文章(《如何弹出一个模式窗口来显示进度条》),会有很多不同的delegate定义。

 

最后一个,使用InvokeBeginInvoke有个需要注意的,就是当子线程在Form_Load开启的时候,会遇到异常,这是因为触发Invoke的对象还没有完全初始化完毕。处理此类问题,在开启线程之前显式的调用“this.Show();”,来使窗体显示在线程开启之前。如果此时只是开启线程来初始化显示数据,那我建议你不要使用子线程,用Splash窗体的效果可能更好。这方面可以参看如下的例子。

http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c95c.aspx#q621q


原创粉丝点击