要实现的效果:点击按纽,窗口上的label上出现1~100数字的变化。

第一个实例(把窗口上的label上文字改成0):

using System;

using System.Windows.Forms;

namespace ThreadTest

{

   public partial class Form1 : Form

  {

    public Form1(){InitializeComponent();}

           private void Form1_Load(object sender, EventArgs e){label1.Text = "0";}    
  }
}
这个是最简单的实例,很容易。
第二个实例(点击button,循环显示0动态变化到100数字):
using System;
using System.Windows.Forms;
namespace ThreadTest
{    
  public partial class Form1 : Form    
  {        
    public Form1(){InitializeComponent();}
           private void Form1_Load(object sender, EventArgs e){label1.Text = "0";}
           private void button1_Click(object sender, EventArgs e)
    {
      for(int i=0;i<101;i++){label1.Text = i.ToString();}
    }    
  }
}
运行一下,点击一下button1,没有看到0~100动态变化,就直接到了100了。 原因:因为你的处理器速度太快了,就只能看到最后的结果。那么,怎样才能看到中间过程呢?
我们先用函数的方式来实现上面的功能,写个名为run的函数: private void run() {     for(int i=0;i<101;i++){         label1.Text = i.ToString();     } }
这样就可以直接调用run函数实现功能了,而不用在事件函数内写代码。
第三个实例(使用函数):
using System;
using System.Windows.Forms;
namespace ThreadTest
{    
  public partial class Form1 : Form    
  {        
    public Form1(){InitializeComponent();}
           private void Form1_Load(object sender, EventArgs e){label1.Text = "0";}

           private void run() {     for(int i=0;i<101;i++){         label1.Text = i.ToString();     } }   
           private void button1_Click(object sender, EventArgs e){run();} 
   }
}
这里就需要在循环过程中加延时了,假定我们每隔1s的延时,lable1的值增加1,方法有很多。
首先我们用一个timer来实现延时。 添加一个timer, 命名为timer1,在timer1的tick事件内添加语句,改变label1的值。(Tick事件是每经过指定时间间隔后被触发)。
第四个实例(使用timer),实现每隔1s的延时,lable1的值增加1,以达到动态变化的效果:
using System;
using System.Windows.Forms;
namespace ThreadTest
{    
  public partial class Form1 : Form    
  {        
     int i;          //全局变量
          public Form1(){InitializeComponent();}

            private void Form1_Load(object sender, EventArgs e){label1.Text = "0";} 
    private void run()
    {     
      i = 0;     
      timer1.Interval = 1000; //设置timer1的间隔时间    
      timer1.Start(); //启动timer1        
    }
    private void timer1_Tick(object sender, EventArgs e)

          {
               i++;            
       if (i > 100) {timer1.Stop();}            
       label1.Text = i.ToString();        
    }    
            private void button1_Click(object sender, EventArgs e) {run();}
   }
}
我们运行一下,能够看到0~100循环的过程了。
以上是我们平常的做法,让label动态变化的效果,下面我们开始使用线程来实现上面的功能。

由于要使用多线程,我们需要引用using System.Threading;
通过下面的语句就定义一个名为thread1的线程 private Thread thread1;
和定义函数极为相似,定义线程之后,就要进行实例化: thread1 = new Thread(new ThreadStart(run));
这个语句的意思就是实例化thread1并将run函数设定为thread1的入口函数(大概意思就是,让run函数在线程thread1上执行)。
创建线程就算完成了,那么怎么运行线程呢? 其实和启动timer1是类似的,thread1.Start();就运行了我们创建的线程thread1。
既然我们创建了线程,那么在关闭窗口的时候,就要撤消线程。添加FormClosing事件,在事件内部写如撤消线程的代码:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
   if (thread1.IsAlive) //判断thread1是否存在,不能撤消一个不存在的线程,否则会引发异常
   { thread1.Abort(); //撤消thread1 }
}
这样才算大功告成,整理的代码如下:(在第三个实例的基础上加以改动)。
第五个实例:
using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest

{

  public partial class Form1 : Form

   {

      private Thread thread1;

    public Form1(){InitializeComponent();}

    private void Form1_Load(object sender, EventArgs e){label1.Text = "0";}

    private void button1_Click(object sender, EventArgs e){thread1 = new Thread(new ThreadStart(run));thread1.Start();}

    private void run(){for (int i = 0; i < 101; i++){label1.Text = i.ToString();}}

            private void Form1_FormClosing(object sender, FormClosingEventArgs e){if (thread1.IsAlive){thread1.Abort();}}    
  }
}
运行一下,按button1,出错了,怎么回事呢?
看看出错原因,是在run函数内的label1.Text = i.ToString();语句上出的错,没错啊,语法正确啊。解释一下,出错的原因是为了保护数据的安全所以不能跨线程调用控件,而label1.Text = i.ToString();句则是在线程thread1上面调用主线程的控件,肯定会出错的!怎么办呢?用委托啊,我的理解就是,线程thread1不能调用主线程的lable1,所以,就委托主线程来改变lable1的值。 首先看一个例子:(从例3改写)(并不创建线程,仅有主线程) 创建一个函数,用来设置lable1的值;

private void set_lableText(string s) { label1.Text = s; } 当需要改变lable1的值时,就调用它,并传递要改变的值。

第六个实例:

using System;

using System.Windows.Forms;

namespace ThreadTest

{

  public partial class Form1 : Form

  {

    public Form1(){InitializeComponent();}

 private void Form1_Load(object sender, EventArgs e){label1.Text = "0";}

private void button1_Click(object sender, EventArgs e){run();    //调用run函数}

private void run(){for(int i=0;i<101;i++){set_lableText( i.ToString() );}}

           private void set_lableText(string s){label1.Text = s;}    
   }
}
实现的功能与第三个实例是一样的,只是,增加了一个函数。
到这里,需要了解一下委托这个东西,我们就需要委托主线程调用函数set_lableText(string s);来改变lable1的值。

首先声明一个委托: delegate void set_Text(string s);

创建一个全局委托变量: set_Text Set_Text;

进行实例化: Set_Text = new set_Text(set_lableText); //括号内的set_lableText是委托要调用的函数(也就是例6写的set_lableText(string s);函数)

现在,就剩下调用委托了,怎么调用委托呢?很简单。 同过Invoke来调用,语句如下:

label1.Invoke(Set_Text, new object[] { i.ToString() }); //Set_Text是调用的委托,object[]则是我们要传递的参数

整理代码如下,第七个实例:

using System;

using System.Threading;

using System.Windows.Forms;

namespace ThreadTest

{

  public partial class Form1 : Form

  {

      private Thread thread1; //定义线程

  delegate void set_Text(string s); //定义委托

  set_Text Set_Text; //定义委托变更

  public Form1(){InitializeComponent();}

  private void Form1_Load(object sender, EventArgs e){label1.Text = "0";       Set_Text = new set_Text(set_lableText); //实例化}

  private void button1_Click(object sender, EventArgs e){thread1 = new Thread(new ThreadStart(run));       thread1.Start();}

  private void set_lableText(string s){label1.Text = s;}//主线程调用的函数

  private void run()

     {

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

        {

          label1.Invoke(Set_Text, new object[] { i.ToString() }); //通过调用委托,来改变lable1的值

          Thread.Sleep(1000); //线程休眠时间,单位是ms

        }

      }

           private void Form1_FormClosing(object sender, FormClosingEventArgs e)        
     {            
        if (thread1.IsAlive) //判断thread1是否存在,不能撤消一个不存在的线程,否则会引发异常            
        {thread1.Abort(); //撤消thread1}
           }
    }
}
这样,一个简单的多线程程序就算完成了。

简单的C#线程开发实例(隔一秒改变一下Label的Text)的更多相关文章

  1. C#一个简单的关于线程的实例

    很多初学者听到线程会觉得晦涩难懂,很多资料一堆专有名词也是让人心烦意乱,本着学习加分享的态度,这里做一个简单的实例分享帮助初学者们初识多线程.  首先大概讲述一下多线程和多进程的区别,任务管理器里各种 ...

  2. Hibernate入门2.简单的项目开发实例

    Hibernate入门2.简单的项目开发实例 这一节通过一个简单的项目学习Hibernate项目的配置 代码下载 : 链接: http://pan.baidu.com/s/1zlgjl 密码: p34 ...

  3. WCF揭秘(一)——简单的WCF开发实例

    一.WCF是什么 WCF是微软为了实现各个开发平台之间的无疑缝连接而开发一种崭新工具,它是为分布式处理而开发.WCF将DCOM.Remoting.Web Service.WSE.MSMQ.AJAX服务 ...

  4. c++简单的ATL COM开发和调用实例(转)

    c++简单的ATL COM开发和调用实例 1.打开VS2010,新建ATL COM 项目,步骤:“文件” -->“新建” -->“项目”,选择“Visual C++” -->“ATL ...

  5. 《HTML 5网页开发实例具体解释》样章、内容简单介绍、前言

    http://spu.jd.com/1167757597.html http://product.dangdang.com/23484942.html 样章 http://download.csdn. ...

  6. Android音乐播放器的开发实例

    本文将引导大家做一个音乐播放器,在做这个Android开发实例的过程中,能够帮助大家进一步熟悉和掌握学过的ListView和其他一些组件.为了有更好的学习效果,其中很多功能我们手动实现,例如音乐播放的 ...

  7. 持久化框架Hibernate 开发实例(一)

    1 Hibernate简介 Hibernate框架是一个非常流行的持久化框架,其中在web开发中占据了非常重要的地位, Hibernate作为Web应用的底层,实现了对数据库操作的封装.HIberna ...

  8. 基于线程开发一个FTP服务器

    一,项目题目:基于线程开发一个FTP服务器 二,项目要求: 基本要求: 1.用户加密认证   2.允许同时多用户登录   3.每个用户有自己的家目录 ,且只能访问自己的家目录   4.对用户进行磁盘配 ...

  9. RDIFramework.NET -.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(WebForm版)

    RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(WebForm版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之 ...

随机推荐

  1. 剑指Offer02 替换空格

    /************************************************************************* > File Name: 02_Replac ...

  2. 解决cell循环利用造成的重复勾选

    @interface ProfessionViewController (){ NSMutableArray *_professionArray;//cell模型数组 NSMutableArray * ...

  3. IntelliJ IDEA 中集成使用git(2015年06月10日)

    前提:需要有一个git账号,https://github.com/ 1.首先需要下载一个Github,https://windows.github.com 安装之后的界面是酱紫的,非常简洁美观 2.在 ...

  4. 9种CSS3炫酷图片展开预览展示动画特效

    详细内容请点击 在线预览立即下载 这是一组共9款CSS3炫酷图片预览展示动画特效插件.css的新特性可以让我们制作出各种炫酷的动画效果.该图片预览展示动画特效就是一个很好的例子,该效果开始时图片堆叠在 ...

  5. IE10 下兼容性问题

    昨天在IE10下遇到这样一个问题 用jquery 获取textarea里的值 其中内容这里包含HTML  用$("#Id").val().$("#Id").ht ...

  6. 【学习笔记】【C语言】数据

    1. 什么是数据 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据.图片数据.视频数据,还有聊QQ时产生的文字数据.用迅 ...

  7. (转)MongoDB分片实战 集群搭建

    环境准备 Linux环境 主机 OS 备注 192.168.32.13 CentOS6.3 64位 普通PC 192.168.71.43 CentOS6.2 64位 服务器,NUMA CPU架构 Mo ...

  8. (转)Yale CAS + .net Client 实现 SSO(2)

    第一部分:安装配置 Tomcat 第二部分:安装配置 CAS 1. 下载 CAS 及.NET CAS client. CAS下载地址:http://www.jasig.org/cas/download ...

  9. C++学习——类的继承

    公有继承(public).私有继承(private).保护继承(protected)是常用的三种继承方式. 1. 公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时, ...

  10. 一个适用于层级目录结构的makefile模版

    今天写了个层次化的Makefile模版,用来自动化编译项目,这个模版应当包含以下功能: 适用于层次化结构,Makefile主要内容都放在顶层目录下的Makefile.env中,子层Makefile包含 ...