C# WinForm多线程(一)----- Thread类库



Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
  
一   关于Thread的说明
  
       在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading命名空间中的。其中提供Thread类用于创建线程,ThreadPool类用于管理线程池等等,此外还提供解决了线程执行安排,死锁,线程间通讯等实际问题的机制。如果你想在你的应用程序中使用多线程,就必须包含这个类。Thread类有几个至关重要的方法,描述如下:
        Start():启动线程
        Sleep( int ):静态方法,暂停当前线程指定的毫秒数
        Abort():通常使用该方法来终止一个线程
        Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。
        Resume():恢复被Suspend()方法挂起的线程的执行
  
 
       线程入口使程序知道该让这个线程干什么事,在C#中,线程入口是通过ThreadStart代理( delegate )来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用 Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。 ThreadState在各种情况下的可能取值如下:
        Aborted:线程已停止
        AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止
        Background:线程在后台执行,与属性Thread.IsBackground有关
        Running:线程正在正常运行
        Stopped:线程已经被停止
        StopRequested:线程正在被要求停止
        Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行)
        SuspendRequested:线程正在要求被挂起,但是未来得及响应
        Unstarted:未调用Thread.Start()开始线程的运行
        WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态
  
二   Winform中使用的thread
  
首先可以看看最直接的方法,也是.net 1.0下支持的方法。但请注意的是,此方法在.net 2.0以后就已经是一种错误的方法了
  
 
public partial class Form1 : Form
  {
      public Form1()
      {
          InitializeComponent();
      }
      private void Form1_Load( object sender, EventArgs e)
      {
          Thread thread = new Thread(ThreadFuntion);
          thread.IsBackground = true ;
          thread.Start();
      }
      private void ThreadFuntion()
      {
          while ( true )
          {
              this .textBox1.Text = DateTime.Now.ToString();
              Thread.Sleep(1000);
          }
      }
  }
  
  
  
这段code 在vs2005或者2008上都抛出异常 :Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on . 这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。那么怎么解决这个问题呢,下面提供几种方案。
  
第一种方案: 在Thread创建之气,将Control.CheckForIllegalCrossThreadCalls 设为 false 。 此代码告诉编译器:在这个类中我们不检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。然而,这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个 static 的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。
  
第二种方案
  
 
namespace TestInvoker
  {
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
  
         private void button1_Click( object sender, EventArgs e)
          {
              Thread thread = new Thread( new ThreadStart(StartSomeWorkFromUIThread));
              thread.IsBackground = true ;
              thread.Start();
              //StartSomeWorkFromUIThread();
              //label1.Text = "Set value through another thread!";
          }
  
         private void StartSomeWorkFromUIThread()
          {
              if ( this .InvokeRequired)
              {
                  BeginInvoke( new EventHandler(RunsOnWorkerThread), null );
              }
              else
              {
                  RunsOnWorkerThread( this , null );
              }
          }
  
         private void RunsOnWorkerThread( object sender, EventArgs e)
          {
              Thread.Sleep(2000);
              label1.Text = System.DateTime.Now.ToString();
          }
      }
  }
  
 
  通过上叙代码,可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform多线程控件的控制了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值