关于多线程的一个例子(UI实时显示)
在开发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实时显示)的更多相关文章
- 使用Uploadify实现上传图片生成缩略图例子,实时显示进度条
不了解Uploadify的,先看看前一篇详细说明 http://www.cnblogs.com/XuebinDing/archive/2012/04/26/2470995.html Uploadify ...
- C语言多线程的一个简单例子
多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
- Deep Learning 32: 自己写的keras的一个callbacks函数,解决keras中不能在每个epoch实时显示学习速率learning rate的问题
一.问题: keras中不能在每个epoch实时显示学习速率learning rate,从而方便调试,实际上也是为了调试解决这个问题:Deep Learning 31: 不同版本的keras,对同样的 ...
- JavaScript实时显示当前时间的例子
用javascript代码在当前页面中实时显示当前时间.代码如下: <html> <head> <title>JavaScript 实时显示当前时间-www.jbx ...
- 【.net 深呼吸】启动一个进程并实时获取状态信息
地球人和火星人都知道,Process类既可以获取正在运行的进程,也可以启动一个新的进程.在79.77%应用场合,我们只需要让目标进程顺利启动就完事了,至于它执行了啥,有没有出错,啥时候退出就不管了. ...
- UI实时预览最佳实践(转)
UI实时预览最佳实践 概要:Android中实时预览UI和编写UI的各种技巧.本文的例子都可以在结尾处的示例代码中看到并下载.如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以 ...
- ASP.NET 多线程 监控任务执行情况,并显示进度条
关于多线程的基本概念和知识在本文中不多讲,而且我懂的也不是很透,说的太多误人子弟...对于我来说,做本文提到的功能够用就行,等实现其他效果不够用的时候,再深入研究 推荐看园子里的两篇博客应该就有个基本 ...
- Android学习总结——实时显示系统时间
我们都知道System.currentTimeMillis()可以获取系统当前的时间,这里要实时显示就可以开启一个线程,然后通过handler发消息,来实时的更新TextView上显示的系统时间.具体 ...
- android 在你的UI中显示Bitmap - 开发文档翻译
由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps in Your UI 在你的UI中显示Bitmap ...
随机推荐
- 腾讯公司数据分析岗位的hadoop工作 线性回归 k-means算法 朴素贝叶斯算法 SpringMVC组件 某公司的广告投放系统 KNN算法 社交网络模型 SpringMVC注解方式
腾讯公司数据分析岗位的hadoop工作 线性回归 k-means算法 朴素贝叶斯算法 SpringMVC组件 某公司的广告投放系统 KNN算法 社交网络模型 SpringMVC注解方式 某移动公司实时 ...
- 源代码编译lamp环境
没有办法用 rpm查询一个源代码包是否安装 因为 并不是用rpm安装的 可以先吧 selinux 给禁用掉 iptables -F 把防火墙规则全部删除 首先确保 gcc gcc-c++ ma ...
- 关于时间,日期,星期,月份的算法(Java中Calendar的用法)(一)
package cn.outofmemory.codes.Date; import java.util.Calendar; import java.util.Date; public class Ca ...
- Jetty:配置JSP支持
选择JSP实现 从Jetty-9.2開始,使用Apache Jasper作为默认JSP容器实现.在前面的版本号中使用的是Glassfish Jasper,在后面的版本号中也能够继续使用它. Jetty ...
- 《生活在Linux中》之:使用Bash就是使用Emacs
定义bash Emacs模式下的快捷键请参考: Readline-在BASH下自定义键盘热键 未完待续...
- 【ASP.NET Web API教程】4.2 路由与动作选择
原文:[ASP.NET Web API教程]4.2 路由与动作选择 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 4.2 Routing ...
- c++/c/java 资源共享群
Hi,我邀请你加入360云盘文件共享群:c++&c&java, 打开邀请链接:http://qun.yunpan.360.cn/10005202 , 输入邀请码:1357
- 将Datagridview中的数据导出至Excel中
首先添加一个模块ImportToExcel,并添加引用 然后导入命名空间: Imports Microsoft.Office.Interop Imports System.Da ...
- UVA11324-- The Largest Clique(SCC+DP)
题目链接 题意:给出一张有向图,求一个结点数最大的结点集,使得该结点集中随意两个结点u和v满足:要么u能够到到v,要么v能够到达u(u和v能够互相到达) 思路:我们能够缩点,用Tarjan求出全部强连 ...
- Java反射机制的使用方法
Java的反射机制同意你在程序执行的过程中获取类定义的细节.有时候在程序执行的时候才得知要调用哪个方法,这时候反射机制就派上用场了. 获取类 类的获取方法有下面几种: forName().通过Clas ...