c# 线程运用

来源:互联网 发布:新海诚 知乎 编辑:程序博客网 时间:2024/05/21 17:22

      Windows系列操作系统是建立在保护模式之上的32位/64位多任务操作系统,其特点是:时分抢先式多任务操作系统。我们来详细探讨一下其中的定义
Windows操作系统是如何来启动一个应用程序(.exe文件):
       操作系统分配一个进程,并向CPU下达一系列指令,包括创建该进程的虚拟内存映射表(关于虚拟内存,请参阅操作系统原理相关书籍,32位保护模式这一概念),分配虚拟内存,设定进程描述符等等,最终将进程封闭到一个独立的虚拟内存地址空间中,返回进程句柄; 操作系统为该进程创建一个线程,并启动它; 该线程从应用程序的Main方法开始执行。 也即是说,所有的Windows进程,都缺省拥有一个线程,这个线程称为主线程;主线程可以根据代码要求创建其它线程,称为辅助线程。

 

操作系统是如何在CPU上调度多个线程:
    Windows操作系统采用了“时分”的概念来调度多个线程,即每个线程占用CPU一段时间后,就会被强行将执行权交给下一个线程。线程轮流来使用CPU。使用CPU的线程,正常执行程序,时间到达时,操作系统执行线程切换操作:将CPU寄存器的内容全部转移到内存中,将另一个线程保存的寄存器状态从内存恢复到寄存器中,由于寄存器中保存了某个线程正在运行哪一行代码的指针,所以切换后另一个线程可以继续上一次运行状态继续运行。这种切换线程的方式称为:现场保存和现场恢复。


控制线程的Thread类和方法
Thread.Start()方法:
开始线程
Thread.IsAlive 属性:
如果此线程已启动并且尚未正常终止或中止,则为 true;否则为 false。
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
Resume():恢复被Suspend()方法挂起的线程的执行。
Thread.ThreadState 属性
     Aborted:线程已停止;
     AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;
     Background:线程在后台执行,与属性Thread.IsBackground有关;不妨碍程序的终止
     Running:线程正在正常运行;
     Stopped:线程已经被停止;
     StopRequested:线程正在被要求停止;
     Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);
     SuspendRequested:线程正在要求被挂起,但是未来得及响应;
     Unstarted:未调用Thread.Start()开始线程的运行;
     WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;

线程的优先级
     由高到低分别是Highest,AboveNormal,Normal,BelowNormal,Lowest;系统默认为ThreadPriority.Normal
     指定优先级的代码:myThread.Priority=ThreadPriority.Lowest;

多线程的优劣
     优点:可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
     缺点:线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
           多线程需要协调和管理,所以需要CPU时间跟踪线程;
           线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
           线程太多会导致控制太复杂,最终可能造成很多Bug;

 


如何的安全的退出线程:
    按照要求,无论使用何种编程语言,线程都必须自然退出,而不应该被迫退出。所谓自然退出。在.net Framework中没有提供任何可以杀死线程的方法,所以我们只能等待线程执行完毕后自然死亡。
    I/强制杀死线程(非安全)....Abord方法:停止线程的执行
     在一个线程中停止另一个线程的执行,此时被终止的线程立即抛出一个ThreadAbortException异常,通过抛出异常跳出线程代码执行。通过try…catch(ThreadAbortException)…段包围线程方法内的代码,可以在线程被中止后得到一个通知。
    I/设置一段时间等待线程之后再调用Abord方法(安全)...Join方法:等待该线程终止。
    在一个父线程(如主线程)调用Join,等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。(Waits for this thread to die.)
 

 

**对于在线程中使用Control类的Invoke方法通过委访问行窗体或控件方法或属性的情况,还有几点注意事项:
I/   窗体不能先于线程销毁。当线程代码运行到Invoke方法时,如果窗体已经被关闭,则会引发异常。此时,窗体必须等待并确保线程确实退出了才能关闭;
II/  不能在创建窗体的线程(一般为主线程)中等待辅助线程结束(调用线程对象的Join方法),因为调用了Join方法的线程会被阻塞(即不再向下运行,而在Join方法上等待),而Invoke方法会向窗体所在线程的消息循环发送执行委托的消息,窗体线程被阻塞后消息循环也会被阻塞(除非调用:Application.DoEvents();//主动调用消息循环 ),Invoke方法自然也会被阻塞,结果就是窗体线程和辅助线程均被阻塞,程序进入死锁;

 

!!!Delegate.Invoke是相当于直接调用。
!!!Control.Invoke是SendMessage,将当前操作同步到界面线程的。 所以我们在Control.Invoke的代理函数尽量不要使用阻滞线程的操作,因为当前线程是主线程。


III/ 解决上述问题的方法很简单:在窗体关闭事件中取消窗体关闭(e.Cancel)并启动一个辅助线程来等候其它辅助线程结束(第64-80行),并在等候成功后由该线程通过委托方法来关闭窗体。用辅助线程来等待其它辅助线程结束,则不会阻塞窗体线程,等待成功后关闭窗体,则可以保证窗体在这些线程退出后才安全关闭。

  

设置前台线程和后台线程
   前台线程(Thread类默认为前台线程):即该线程会阻止进程结束。即便主线程结束了,只要进程中还有一个前台线程尚未结束,则进程不会结束,直到所有的前台线程都结束。这是最安全的一种方式,保证线程在结束前做完其所有工作。
   后台线程(不涉及I/O操作的线程)-既IsBackground=True :只要主线程退出,这些线程就会被强制结束。
http://msdn.microsoft.com/zh-cn/library/7a2f3ay4(VS.80).aspx

------------------------
BackgroundWorker--后台操作控件
★BackgroundWorker实现WinForm异步操作/演练:在后台运行操作
如果有一个需要很长时间才能完成的操作,而且不希望用户界面中出现延迟,则

可以使用

BackgroundWorker 类来在另一个线程上运行该操作。
事件:
1,ReportProgress的调用将会导致ProgressChanged事件被触发。

ProgressChanged event handler用于

显示当前进度、当前记录数量和显示获取的纪录:

2,如何操作正常地结束,BackgroundWorker的RunWorkerCompleted会被触发
注:如果操作需要操作UI上的控件,只能在Main Thread中进行。如何在

RetrieveData方法进行的话,由

于该方式是一个异步方法,是会抛出异常的。
方法:
1,this.backgroundWorkerLeft.RunWorkerAsync(object);//开始
RunWorkerAsync方法被掉调用,我们定义的常量(object )当作参数被掺入。随

后,将会触发其DoWork

事件
this.backgroundWorkerLeft.CancelAsync();//手工结束掉当前的操作
 

------------------------------------------------------------------------

多线程 实现返回值 任意参数

1,使用委托异步

2,


http://hi.baidu.com/ccm_8730/blog/item/626f95091c81e82d6a60fb38.html