C# 线程基础参考

1、使用线程的情况

① 程序需要执行和两个和多个任务

② 程序要等待某事件的发生:例如用户输入、文件操作、网络操作和搜索

③ 后台程序


2、多线程的并发执行

如果有多个线程在执行,单CPU只有一个,到底执行的哪个?

① 如果一个线程连续占用CPU资源时间过长,其它的资源得不到执行,则系统会强制的切换执行其它线程。(强制剥夺)

② 如果一个线程没事可做、CPU可执行其它线程。(主动放弃)

③ 这是由操作系统的调度机制决定的,不同的操作系统调度机制不一样。一般无法精确的预料多线程的执行顺序,在程序设计的时候应特别注意。


3、创建并启动线程

ThreadStart 线程启动委托名=new ThreadStart(方法名);
Thread 线程实例名
=new Thread(线程启动委托名);
线程实例名.Start();


4、终止线程

① 线程实例名.Abort():用此方法的后果是不可恢复的终止线程。

② 线程实例名.Interrupt():中断后可恢复。


5、休眠线程

① 线程实例名.Sleep():

  当线程Sleep时,系统就立即退出执行队列一段时间,当睡眠结束时,系统会产生一个时钟中断,从而使线程回到执行队列中,从而恢复线程的执行。


6、挂起/恢复线程

① 线程实例名.Suspend():

  挂起与线程休眠不同,线程的挂起不会使线程立即停止执行,直到线程到达安全点之后它才可以将该线程挂起,如果线程尚未启动或已经停止,则它将不能挂起。

② 线程实例名.Resume():恢复将使一个线程跳出挂起状态并使该线程继续执行。

  一个线程不能对另一个线程调用Sleep() ,但是一个线程可以对另一个线程调用Suspend()。

  还可以使用许多其它的方式来阻塞线程。例如,可以通过调用 Thread.Join 使一个线程等待另一个线程(子线程)停止。使用Monitor.Wait使一个线程等待访问一个同步对象。


7、串行化线程

① 线程实例名.jion():

  例如在主线程中插入t.jion(),主线程执行到这条语句后,主线程(当前线程)立即进入阻塞状态.直到t运行完后阻塞状态才解除。

  相当于把t的任务插入或串联到主线程中,把两条线索串联成一条线索。


8、线程的锁定机制

  线程的锁定机制可以保证每次只有一个线程可以访问共享资源。

  使用关键字lock:

① ock语句的语法

  lock(对象引用)语句块;

② lock语句的功能

  当对象被lock 锁定时,访问该线程的其它线程会进入等待的状态。

③ 对象锁机制保证了对象访问的完整性:只有一个线程完成操作后,其它的线程才能进行操作。

④ 一般情况下,当一个线程写某个变量,而同时可能有其它的线程读或写这个变量时,为了保持数据的一致性应该使用锁定机制。

⑤ 线程的安全性

  线程安全性就是保护的类的成员和代码的安全,从而使他们不会同时被几个线程中断,使用锁定机制。

⑥ 多线程公用一个对象时,就不应该使用lock关键字了,这里Monitor,Monitor提供了使线程共享资源的方案。

  Monitor类可以锁定一个对象,一个线程只有得到这把锁才可以对该对象进行操作。

  如:
  Monitor.Enter(obj);
  Monitor.Exit(obj);

⑦ 临界区和锁

  当谈论多线程应用程序的时候,首先应该想到的就是并发性问题。尽管这对于同时执行多个任务的程序是很有用的,但通常都是危险的。

  为了解决这个问题,在C#中提出了临界区和锁的概念。在程序设计中,临界区是一块在任何时候只能有一个进程进入的区域。

  在C#中通过语句lock来声明临界区。lock声明后面的代码,不管是以行还是一块代码,在同一时间最多只能有一个进程执行。
 

9、线程的优先级具有不可靠性,就是说不能用优先级来控制线程的执行顺序。


10、后台线程

① 什么是后台线程?

  比起应用程序的主图形用户界面(GUI)线程来说,这些线程以较低的优先权在不同的过程中运行着。对于不能立即执行结束,又不想一直等待的任务,后台线程能很好的胜任。

  在C#中,把线程对象的IsBackground属性设为true,该线程即为后台线程。

  后台线程跟前台线程只有一个区别,那就是后台线程不妨碍程序的终止。一旦一个进程所有的前台线程都终止后,CLR将通过调用任意一个存活中的后台进程的Abort()方法来彻底终止进程。

  注意:后台线程不能直接操作所在进程之外的数据引用。

② 怎样与后台线程通讯?

  运用MethodInvoker委派实体。

  也可在初始化(构造函数)中加入下面一句即可实现通讯:

  Control.CheckForIllegalCrossThreadCalls = False;

要使用MethodInvoker委派,需要三个条件:

a、一个创建委派的后台线程

  Thread thread=new Thread(new ThreadStart(Run));

  thread.IsBackground=true;//把Thread设为后台线程

  thread.Start();


b、一个用作后台线程与前台可视化单元的接口的类级方法

public void Run()
{
  int count=0;
  try
  {
    //创建一个委托,UpdateLabel是该委托所托管的代码,必须是声明为void 且不接受任何参数的任何方法。
    MethodInvoker mi=new MethodInvoker(this.UpdateLabel);       
    while(true)
    {
      count++;
       //this.Invoke(mi);//同步执行委托
      this.BeginInvoke(mi);//异步执行委托
      Thread.Sleep(500);
    }
  }
  catch(ThreadInterruptedException e)
  {
    Console.WriteLine("Interruption Exception in Thread:{0}",e);
  }
  catch(Exception ex)
  {
    Console.WriteLine("Exception in Thread:{0}",ex);
  }
}


c、一个应用程序中可以更新的可视化单元

public void UpdateLabel()
{
  label1.Text=count.ToString();
}

 



参考:http://cfg1014.blog.163.com/blog/static/663439920096991337523/?hasChannelAdminPriv=true

posted @ 2011-04-21 11:17  Wiliz  阅读(492)  评论(0)    收藏  举报