zoukankan      html  css  js  c++  java
  • C#中的多线程(摘自网络)

    一.多线程的概念 

    Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。 

    多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望自己的程序很多时候没事可干,在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。 

    然而我们也必须认识到线程本身可能影响系统性能的不利方面,以正确使用线程: 

    线程也是程序,所以线程需要占用内存,线程越多占用内存也越多 
    多线程需要协调和管理,所以需要CPU时间跟踪线程 
    线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题 
    线程太多会导致控制太复杂,最终可能造成很多Bug 

    基于以上认识,我们可以一个比喻来加深理解。假设有一个公司,公司里有很多各司其职的职员,那么我们可以认为这个正常运作的公司就是一个进程,而公司里的职员就是线程。一个公司至少得有一个职员吧,同理,一个进程至少包含一个线程。在公司里,你可以一个职员干所有的事,但是效率很显然是高不起来的,一个人的公司也不可能做大;一个程序中也可以只用一个线程去做事,事实上,一些过时的语言如fortune,basic都是如此,但是象一个人的公司一样,效率很低,如果做大程序,效率更低——事实上现在几乎没有单线程的商业软件。公司的职员越多,老板就得发越多的薪水给他们,还得耗费大量精力去管理他们,协调他们之间的矛盾和利益;程序也是如此,线程越多耗费的资源也越多,需要CPU时间去跟踪线程,还得解决诸如死锁,同步等问题。总之,如果你不想你的公司被称为“皮包公司”,你就得多几个员工;如果你不想让你的程序显得稚气,就在你的程序里引入多线程吧! 

    本文将对C#编程中的多线程机制进行探讨,通过一些实例解决对线程的控制,多线程间通讯等问题。为了省去创建GUI那些繁琐的步骤,更清晰地逼近线程的本质,下面所有的程序都是控制台程序,程序最后的Console.ReadLine()是为了使程序中途停下来,以便看清楚执行过程中的输出。 

    好了,废话少说,让我们来体验一下多线程的C#吧! 
    二.操纵一个线程

    任何程序在执行时,至少有一个主线程,下面这段小程序可以给读者一个直观的印象:

    //SystemThread.cs 
    using System; 
    using System.Threading; 

    namespace ThreadTest 

      
    class RunIt 
      

        [STAThread] 
        
    static void Main(string[] args) 
        

          Thread.CurrentThread.Name
    ="System Thread";//给当前线程起名为"System Thread" 
    Console.WriteLine(Thread.CurrentThread.Name+"'Status:"+Thread.CurrentThread.ThreadState); 
          Console.ReadLine(); 
        }
     
      }
     
    }
     

    编译执行后你看到了什么?是的,程序将产生如下输出: 

    System Thread's Status:Running 

    在这里,我们通过Thread类的静态属性CurrentThread获取了当前执行的线程,对其Name属性赋值“System Thread”,最后还输出了它的当前状态(ThreadState)。所谓静态属性,就是这个类所有对象所公有的属性,不管你创建了多少个这个类的实例,但是类的静态属性在内存中只有一个。很容易理解CurrentThread为什么是静态的——虽然有多个线程同时存在,但是在某一个时刻,CPU只能执行其中一个。 

    就像上面程序所演示的,我们通过Thread类来创建和控制线程。注意到程序的头部,我们使用了如下命名空间: 
    以下内容为程序代码:

    using System; 
    using System.Threading; 

    在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading命名空间中的。其中提供Thread类用于创建线程,ThreadPool类用于管理线程池等等,此外还提供解决了线程执行安排,死锁,线程间通讯等实际问题的机制。如果你想在你的应用程序中使用多线程,就必须包含这个类。Thread类有几个至关重要的方法,描述如下: 

    Start():启动线程 
    Sleep(int):静态方法,暂停当前线程指定的毫秒数 
    Abort():通常使用该方法来终止一个线程 
    Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。 
    Resume():恢复被Suspend()方法挂起的线程的执行 
    下面我们就动手来创建一个线程,使用Thread类创建线程时,只需提供线程入口即可。线程入口使程序知道该让这个线程干什么事,在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。 

    打开你的VS.net,新建一个控制台应用程序(Console Application),下面这些代码将让你体味到完全控制一个线程的无穷乐趣!

    //ThreadTest.cs 

    
    using System; 
    
    using System.Threading; 

    
    namespace ThreadTest 
    

    
    public class Alpha 
        

          
    public void Beta() 
          

            
    while (true
            

              Console.WriteLine(
    "Alpha.Beta is running in its own thread."); 
            }
     
          }
     
        }


        
    public class Simple 
        

          
    public static int Main() 
          

            Console.WriteLine(
    "Thread Start/Stop/Join Sample"); 

            Alpha oAlpha 
    = new Alpha(); 
            
    //这里创建一个线程,使之执行Alpha类的Beta()方法 
            Thread oThread = new Thread(new ThreadStart(oAlpha.Beta)); 
            oThread.Start(); 
            
    while (!oThread.IsAlive); 
            Thread.Sleep(
    1); 
            oThread.Abort(); 
            oThread.Join(); 
            Console.WriteLine(); 
            Console.WriteLine(
    "Alpha.Beta has finished"); 
            
    try 
            

              Console.WriteLine(
    "Try to restart the Alpha.Beta thread"); 
              oThread.Start(); 
            }
     
            
    catch (ThreadStateException) 
            

              Console.Write(
    "ThreadStateException trying to restart Alpha.Beta. "); 
              Console.WriteLine(
    "Expected since aborted threads cannot be restarted."); 
              Console.ReadLine(); 
            }
     
            
    return 0
          }
     
        }
     
      }
     

    这段程序包含两个类Alpha和Simple,在创建线程oThread时我们用指向Alpha.Beta()方法的初始化了ThreadStart代理(delegate)对象,当我们创建的线程oThread调用oThread.Start()方法启动时,实际上程序运行的是Alpha.Beta()方法: 

    Alpha oAlpha = new Alpha(); 
      Thread oThread = new Thread(new ThreadStart(oAlpha.Beta)); 
      oThread.Start(); 

    然后在Main()函数的while循环中,我们使用静态方法Thread.Sleep()让主线程停了1ms,这段时间CPU转向执行线程oThread。然后我们试图用Thread.Abort()方法终止线程oThread,注意后面的oThread.Join(),Thread.Join()方法使主线程等待,直到oThread线程结束。你可以给Thread.Join()方法指定一个int型的参数作为等待的最长时间。之后,我们试图用Thread.Start()方法重新启动线程oThread,但是显然Abort()方法带来的后果是不可恢复的终止线程,所以最后程序会抛出ThreadStateException异常。 
    在这里我们要注意的是其它线程都是依附于Main()函数所在的线程的,Main()函数是C#程序的入口,起始线程可以称之为主线程,如果所有的前台线程都停止了,那么主线程可以终止,而所有的后台线程都将无条件终止。而所有的线程虽然在微观上是串行执行的,但是在宏观上你完全可以认为它们在并行执行。

  • 相关阅读:
    树链剖分 (模板) 洛谷3384
    ST表 (模板) 洛谷3865
    IOI 2005 River (洛谷 3354)
    IOI 2005 River (洛谷 3354)
    poj1094 Sorting It All Out
    poj1094 Sorting It All Out
    spfa(模板)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    HAOI 2006 受欢迎的牛 (洛谷2341)
    洛谷1850(NOIp2016) 换教室——期望dp
  • 原文地址:https://www.cnblogs.com/wzyexf/p/687259.html
Copyright © 2011-2022 走看看