博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于多线程的一个例子(UI实时显示)
阅读量:5092 次
发布时间:2019-06-13

本文共 3145 字,大约阅读时间需要 10 分钟。

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

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
(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

转载于:https://www.cnblogs.com/Events/p/4064278.html

你可能感兴趣的文章
Hibernate简介
查看>>
Python自学之乐-python中break continue exit() pass浅析
查看>>
局域网从另一台电脑copy文件(Linux系统下)
查看>>
FC和SCSI
查看>>
VC2010常见问题的解决方案
查看>>
超级详细Tcpdump 的用法
查看>>
程序员的思维修炼
查看>>
display:none和visibility:hidden的区别
查看>>
HDOJ---1232 畅通工程[并查集]
查看>>
Python学习路程-常用设计模式学习
查看>>
[JOYOI1326] 剑人合一
查看>>
[JZOJ100047] 【NOIP2017提高A组模拟7.14】基因变异
查看>>
梦断代码阅读笔记01
查看>>
利用“Java同包同名类执行顺序”取消Java 网站应用程序Licence验证
查看>>
UNICODE与ASCII码的关系(MTK)
查看>>
underscore源码学习笔记(一)
查看>>
iOS项目开发实战——通过Http Get方式与server通信
查看>>
ES6 Number
查看>>
Java基础学习-IO流
查看>>
TFS 2017 持续集成速记
查看>>