要实现的效果:点击按纽,窗口上的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. CSS图片翻转例子

                      dfdfdfdfdf <!DOCTYPE html> <html> <head> <meta charset=" ...

  2. WebAPI GET和POST请求的几种方(转发)

    WebAPI GET和POST请求的几种方式 GET请求 1.无参数get请求 一般get请求有两种写法,一种是$.get()   一种是$.ajax({type:"get"}), ...

  3. 正确理解SQL Server的许可证(转)

    今天在论坛上看到有人讨论如果使用SQL Server作为SEPM的后台数据库,需要多少个CAL的问题:   If I do have to use SQL Server what type of li ...

  4. Document.getElementById 与 $('#id')的区别

    一直认为jquery中的$("#id")和document.getElementByIdx_x("id")得到的效果是一样的,今天才发现并不是这么一回事,通过测 ...

  5. 增强for循环用法___ArrayList数组实现使用下标最好,LinkedList使用增强型的(转载)

    总结: 1.For-Each循环的缺点:丢掉了索引信息. 当遍历集合或数组时,如果需要访问集合或数组的下标,那么最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循环,因为它丢失了下标信息. ...

  6. SDWebImage缓存清理

    //计算缓存大小 [SDImageCache sharedImageCache] getSize] //清理缓存 SDImageCache *sd = [[SDImageCache alloc]ini ...

  7. 一个基于MBProgressHUD的自定义视图hud例子

    项目中用到的一个hud,基于MBProgressHUD,使用自定义视图实现的,动画效果是从网上参考的,并不是很理想.有需要的可以看看,这里是源码(源码用了cocoapods,运行前需要pod inst ...

  8. (转)Linux性能调优之虚拟内存篇

    简单地说,虚拟内存就是硬盘中的一块区域,它用来存放内存里使用频率不高的页面文件.好处是为了提高内存的利用率 - 让使用频率高的页面文件活动在内存区域中,提高CPU对数据操作的速度.在Linux中,这个 ...

  9. arcgis js api 本地化配置

    配置arcgis library 根目录的init.js的 "baseUrl:",使其指向正确的地址

  10. template_20_实现智能指针

    一:计数器二:析构和释放三:SmartPoint