线程基本概念(基础)

关于线程

 

    1.什么是线程?(从机器的CPU角度看)一个线程是程序执行的一个单独过程。一个线程不能够被任何底层的事件中断,并且不包括执行更小的过程。

 

    2.如何在程序中使用线程?首先,必须有一个线程函数。然后,创建线程对象。在一个线程开始的时候,调用该程序以执行线程的实际工作。当这个程序终止时,该线程也终止了。因此,为了能使线程程序继续在后台执行,必须在线程程序中内建一个循环机制。如下面的例子:

  protected void ThreadFunc()

   {

    bool done=false;

    int counter=0;

    while(!done)

    {

      Thread.Sleep(1000);

      counter++;

      Console.WriterLine("Counter:{0}",counter);  

    }

  }

  然后,创建一个线程,并启动它运行:

  Thread fThread=new Thread(new ThreadStart(ThreadFunc));

  fThread.Start();

   注意:首先,为了在应用程序中使用线程,必须将System.Threading类库作为应用包括到应用程序中。其次,C#能过使用对象的方法作为线程程序。如下:

  Class1 c1=new Class1();

  Thread fThread=new Thread(new ThreadStart(c1.ThreadFunc));

  fThread.Start();

  

  3.如何停止线程?运用Thread类的AbortInterrupt方法。

  fThread.Abort();

  fThread.Interrupt();

  

  4.什么是后台线程?比起应用程序的主图形用户界面(GUI)线程来说,这些线程以较低的优先权在不同的过程中运行着。对于不能立即执行结束,又不想一直等待的任务,后台线程能很好的胜任。在C#中,把线程对象的IsBackground属性设为true,该线程即为后台线程。

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

 

  5.怎样与后台线程通讯?运用MethodInvoker委派实体。

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

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

  Thread fThread=new Thread(new ThreadStart(ThreadFunc));

  fThread.IsBackground=true;

  fThread.Start();

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

  public void ThreadFunc()

  {

    try

    {

      MethodInvoker mi=new MethodInvoker(this.UpdateLabel);

      while(true)

      {

        bCounter++;

        this.BeginInvok(mi);

        Thread.Sleep(500);

      }

    }

    catch(ThreadInterruptedException e)

    {

      Console.WriteLine("Interruption Exception in Thread:{0}",e);

    }

    catch(Exception we)

    {

      Console.WriteLine("Exception in Thread:{0}",we);

    }

  }

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

  public void UpdateLabel()

  {

    label1.Text=bCounter.ToString();

  }

  

  6.临界区和锁的概念?当谈论多线程应用程序的时候,首先应该想到的就是并发性问题。尽管这对于同时执行多个任务的程序是很有用的,但通常都是危险的。为了解决这个问题,在C#中提出了临界区和锁的概念。

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

  int nValue=0;

  lock

  {

    index++;

    if(index>MaxIndex)

      return;

    nValue=Value[index];

  }

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

 C#创建多线程应用程序
关键词: C#创建多线程应用程序


使用多线程技术能有效地帮助你实现应用程序的更高性能和更优良的可伸缩性。但在真正运用这项技术的时候务必小心。本文是对线程技术所牵扯的工具和技术问题系列文章的开篇。我首先对线程概念进行介绍,然后总结一些常用的构造,最后介绍它们的用法。

线程的两面性

用Java语言编写多线程程序并不难,这是好事也是坏事。微软在开发C#时,他们把这种易用性的窘境全盘照搬到了整个新平台上。同时,C#相比Java具有更多的程序原语,但是Thread对象和同步监视器的基本Java原语从形式和功能上看都已足够提供强大的线程编程能力了。因此,在决定为应用程序采用多线程技术之前务必小心。

为什么不用多线程
首先得记住,在决定是否采用多线程技术时,除非你正在玩代码,否则千万别因为多线程编程够“酷”而简单地使用线程技术编程。多线程编程技术太时髦了,如果你不小心点你的老板迟早也会着迷,那时你就死定了。其次,不要因为让程序运行得更快而轻易采用多线程,除非你真的能证明单线程实现确实慢得可以。最后,在冒昧地一头扎进多线程机制之前,先回忆下微软所提供的一种公寓(apartment)模型,也就是把对象写成单线程构造而运行在多线程环境下。所以,说来说去,你并不一定非要采用多线程编码。不过,公寓模型是另外一个话题了。

如果做得不对,多线程编程势必会打开“潘朵拉的盒子”(意思是说惹出无数的麻烦)。重复性不明显、产生程序垃圾、记数器没有正确增值等等。你的应用程序还可能突然挂起。例如,数据库连接这类资源就可能出人意料地关闭或者变得过载。高级开发人员所面临的一个大麻烦就是解决线程问题。这些大问题不花点时间休想解决,而且它们对产品交货日期以及产品可靠性产生了严重的负面影响。

为什么要用多线程
如果你的应用程序需要采取以下的操作,那么你尽可在编程的时候考虑多线程机制:

连续的操作,需要花费忍无可忍的过长时间才可能完成
并行计算
为了等待网络、文件系统、用户或其他I/O响应而耗费大量的执行时间
所以说,在动手之前,先保证自己的应用程序中是否出现了以上3种情形。

如果你的代码运行得足够快,但是你认为你能让它运行得更快(假设你确实有这本事),我劝你最好不要接受这种诱惑。如果你不能肯定程序的计算操作并行性(例如针对同一数据表的并发数据库更改——当你的数据库达到了数据表级锁定的情况下),那么再想想其他法子吧。还有,如果你不知道应用程序是否因为等待输入或输出而花费了过多的时间,那么请首先搞清楚真正耗费时间的情况再说。实际上,启动3个线程以百万分之一的步长计算圆周率所消耗的时间就比同一线程重复计算3次要长得多。为什么会出现这种失败的情形呢?原因就在于,虽然第2条并行计算确实可用,但设计者却恰恰忽略了以上第3个标准:并行计算可以用到的一次计算期间却没有空闲周期。

假如你在为一台装备了多个处理器的并行计算机编写程序,则以上规则在这种情况下例外,你可以通过适当的并行操作设计而令软件性能大大获益——哪怕每一操作都对CPU时间极其贪婪。

基本的线程管理工具
刚才我已经为多线程编程提出了相当程度的警告,同时还为何时使用或者不使用多线程提出了建议,接下来我对多线程编程所能利用的某些工具进行阐述。                                         
在.NET和C#中编写一个多线程应用程序将非常得容易。即使对于那些从没有用C#编写过多线程应用程序的初学者,只需遵循以下这些简单的步骤就可以实现目的。

定义名称空间

在.NET中,多线程功能是在System.Threading名称空间中定义的。因此,在使用任何线程类之前,必须定义 System.Threading名称空间。定义方法如下:

using System.Threading;

启动线程

System.threading名称空间中的Thread类代表一个线程对象,用这个类对象可以创建新的线程,删除、暂停和恢复线程。 下面的代码使用Thread类创建一个新的线程,然后启动这个线程:

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

thread.Start();

其中WriteData是这个线程要执行的一个函数,代码如下:

protected void WriteData()

{

string str ;

for ( int i = 0; i<=10000; i++ )

{

str = "Secondary Thread" + i.ToString();

Console.WriteLine(listView1.ListItems.Count, str, 0, new string[]{""} );

Update();

}

}

杀死线程

Thread类的Abort方法用于永久地杀死一个线程。但是请注意,在调用Abort方法前一定要判断线程是否还激活,也就是判断thread.IsAlive的值:

if ( thread.IsAlive )

{

thread.Abort();

}

暂停线程

Thread.Sleep方法用于将一个线程暂停一段时间,代码如下:

thread.Sleep();

设置线程的优先权

我们可以使用Thread类的ThreadPriority属性设置线程的优先权。线程优先权的取值范围是Normal、AboveNormal、BelowNormal、Highest或者Lowest。请看下面的设置代码:

thread.Priority = ThreadPriority.Highest;

延迟线程

Thread类的Suspend方法可以延迟一个线程。线程被延迟到调用Resume方法为止。

if (thread.ThreadState = ThreadState.Running )

{

thread.Suspend();

}

恢复被延迟的线程

调用Resume方法可以恢复一个被延迟的线程。如果线程没有被延迟,Resume方法就是无效的。

if (thread.ThreadState = ThreadState.Suspended )

{

thread.Resume();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值