在开发Window应用程序的时候,经常需要在界面上显示出已经执行到什么步骤了,拿一个简单例子来说,创建一个Winform程序,在窗体上访一个Button和一个Label,点击Button时做100次循环,在Label上实时显示当前循环的次数。一种简单的做法就是使用Application.DoEvents,代码如下:

private void btnTest_Click(object sender, EventArgs e)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
label1.Text = i + "/100";
Application.DoEvents();
}
}

上面的代码如果将Application.DoEvents();去掉当点击Button时,程序会卡住,直到这个循环执行完成,当这个循环足够大时是不能忍受的。不过小数据量用Application.DoEvents()还行,数据量大了使用Application.DoEvents()就会带来性能的问题。所以Application.DoEvents()要慎用,在大数据量的时候可以使用多线程解决。如下:

private void btnTest_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
}
private void DoWork()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
label1.Text = i + "/100";
}
}

嗯?出现异常了是吧,没错上面的代码运行后后会出现“线程间操作无效: 从不是创建控件“label1”的线程访问它。”的异常。关于什么原因造成的,大家可以google一下。不过上面代码在vs03中貌似可以正常运行。将代码改成下面这样就可以正常运行了:

private void btnTest_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
}
private void DoWork()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action<string>(this.ChangeLabel),i.ToString());
}
}
private void ChangeLabel(string i)
{
label1.Text = i + "/100";
}

如果嫌多写一个ChangeLabel方法费事,可以写成匿名方法的形式,如下:

private void btnTest_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
}
private void DoWork()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action(delegate(){label1.Text=i+"/100";}));
}
}

同样可以使用匿名方法的方式将DoWork方法也去掉:

private void btnTest_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(delegate() {
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action(delegate() { label1.Text = i + "/100"; }));
}
}));
thread.Start();
}

如果想传参数到Dowork方法中,那么就不能使用ThreadStart类了,应该使用ParameterizedThreadStart类,如下:

private void btnTest_Click(object sender, EventArgs e)
{
string name = "oec2003";
Thread thread = new Thread(new ParameterizedThreadStart(DoWork));
thread.Start(name);
}
private void DoWork(object name)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action(delegate(){label1.Text=name+":"+ i+"/100";}));
}
}

同样我们也可以使用线程池的方式来实现

private void btnTest_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
}
private void DoWork(object o)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action(delegate(){label1.Text=i+"/100";}));
}
}

使用匿名方法的方式:

private void btnTest_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
this.Invoke(new Action(delegate() { label1.Text = i + "/100"; }));
}
}));
}

平时做Windows应用程序很少,对多线程理解也不是特别深入,有什么不对的地方往大家指正。

[转自]http://www.cnblogs.com/oec2003/archive/2009/12/20/1628412.html

关于多线程的一个例子(UI实时显示)的更多相关文章

  1. 使用Uploadify实现上传图片生成缩略图例子,实时显示进度条

    不了解Uploadify的,先看看前一篇详细说明 http://www.cnblogs.com/XuebinDing/archive/2012/04/26/2470995.html Uploadify ...

  2. C语言多线程的一个简单例子

    多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  3. Deep Learning 32: 自己写的keras的一个callbacks函数,解决keras中不能在每个epoch实时显示学习速率learning rate的问题

    一.问题: keras中不能在每个epoch实时显示学习速率learning rate,从而方便调试,实际上也是为了调试解决这个问题:Deep Learning 31: 不同版本的keras,对同样的 ...

  4. JavaScript实时显示当前时间的例子

    用javascript代码在当前页面中实时显示当前时间.代码如下: <html> <head> <title>JavaScript 实时显示当前时间-www.jbx ...

  5. 【.net 深呼吸】启动一个进程并实时获取状态信息

    地球人和火星人都知道,Process类既可以获取正在运行的进程,也可以启动一个新的进程.在79.77%应用场合,我们只需要让目标进程顺利启动就完事了,至于它执行了啥,有没有出错,啥时候退出就不管了. ...

  6. UI实时预览最佳实践(转)

    UI实时预览最佳实践 概要:Android中实时预览UI和编写UI的各种技巧.本文的例子都可以在结尾处的示例代码中看到并下载.如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以 ...

  7. ASP.NET 多线程 监控任务执行情况,并显示进度条

    关于多线程的基本概念和知识在本文中不多讲,而且我懂的也不是很透,说的太多误人子弟...对于我来说,做本文提到的功能够用就行,等实现其他效果不够用的时候,再深入研究 推荐看园子里的两篇博客应该就有个基本 ...

  8. Android学习总结——实时显示系统时间

    我们都知道System.currentTimeMillis()可以获取系统当前的时间,这里要实时显示就可以开启一个线程,然后通过handler发消息,来实时的更新TextView上显示的系统时间.具体 ...

  9. android 在你的UI中显示Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps in Your UI 在你的UI中显示Bitmap ...

随机推荐

  1. javascript中apply和eval结合的强大用法

        eval是一个函数,可以接受一个参数,这个参数可以作为js语句被解释性的执行,利用这个特性,eval和apply结合起来,可以大大简化代码  如下例子 <a class="cl ...

  2. 关于yaf的控制器命名,一个纠结的问题(续)

    以下方案缺少loader相关的步骤,明天补上!!! 前面写过一篇<关于yaf的控制器命名,一个纠结的问题>.没想到yaf群里面也有跟我遇到一样问题的人,分享下解决办法. 写完那篇博文后,我 ...

  3. Oracle实用-01:绑定变量

    数据库虽然在学校系统学习过,但是在工作中真正使用起来收获又是不一样的,今天起打算将项目中使用到的技术再分享出来,不以书本的顺序,只从碰到的问题为顺序. 虽然不是纯粹的数据库工程师,但是每个程序员总免不 ...

  4. Mahout-Pearson correlation的实现

    计算公式: 并通过以下代码对Mahout in Action的结果进行了验证: 代码例如以下: ` package com.example.mahout; public class TestColl ...

  5. Linux红黑树(二)——访问节点

    核心对红黑树使用两点说明 1.头文件 <Documentation/rbtree.txt> Linux's rbtree implementation lives in the file ...

  6. HDU1849 Rabbit and Grass()

    用异或看取得的值是否为0推断 思想换没搞懂 #include<stdio.h> int main() { int ans,n,a; while(scanf("%d",& ...

  7. EndNote是一款着名的参考文献管理软件

    EndNote是一款着名的参考文献管理软件,我们可以通过该软件创建个人参考文献库,此外对公司DCC.法务和专 利部门十分的有用,甚至对我们写SOP 也有些帮忙,并且该软件可以在其中加入文本.图像.表格 ...

  8. Apache Lucene

    1.Lucene  -全文搜索引擎 Apache Lucene 是一个基于Java的全文搜索引擎,利用它能够轻易的为Java软件添�全文搜索引擎的功能. Lucene最重要的工作是替文件的每个字索引, ...

  9. 对称加密算法DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES。

    对称加密算法:DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES. 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文 ...

  10. java中怎么终止一个线程的执行----个人学习心得

    参考了一下两个网站的介绍: ①:http://blog.csdn.net/liuhanhan512/article/details/7077601 ②:http://www.blogjava.net/ ...