开发者社区> 醉意人间> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

WinForm 多线程

简介: http://www.cnblogs.com/yencain/articles/1375616.html 环境:VS2008、C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来。
+关注继续查看

http://www.cnblogs.com/yencain/articles/1375616.html

环境:VS2008、C#3.0

在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来。一个最直接的方法便是使用多线程。多线程编程的方式在WinForm开发中必不可少。

本文介绍在WinForm开发中如何使用多线程,以及在线程中如何通过Control.Invoke方法返回窗体主线程执行相关操作。

-. WinForm多线程编程
1. new Thread()
    新开一个线程,执行一个方法,没有参数传递:

private void DoWork() {
            Thread t 
= new Thread(new ThreadStart(this.DoSomething));
            t.Start();
 }

private void DoSomething() {
            MessageBox.Show(
"thread start");
 }

新开一个线程,执行一个方法,并传递参数:

private void DoWork() {
            Thread t = new Thread(new ParameterizedThreadStart(this.DoSomething));
            t.Start("guozhijian");
}
private void DoSomething(object o) {
            MessageBox.Show(o.ToString());
}

参数定义为object类型。

2. ThreadPool
    众所周知,新开一个线程代价是很高昂的,如果我们每个操作都新开一个线程,那么太浪费了,于是,下面使用线程池。
    无参数传递:

private void DoWork() {
            ThreadPool.QueueUserWorkItem(
new WaitCallback(this.DoSomething));
}

private void DoSomething(object o) {
            MessageBox.Show(
"thread start");
}

有参数传递:

private void DoWork() {
            ThreadPool.QueueUserWorkItem(
new WaitCallback(this.DoSomething), "guozhijian");
}

private void DoSomething(object o) {
            MessageBox.Show(o.ToString());
}

使用匿名方法更灵活:

private void DoWork() {
            
string name = "guozhijian";
            ThreadPool.QueueUserWorkItem(
new WaitCallback(delegate(object o){
                MessageBox.Show(name);
            }
));
}

在匿名代码段里面可以直接访问局部变量,不用在关心参数传递的问题

二. Invoke
1. this.Invoke
现在,在业务线程里面执行完毕,要改变窗体控件的值了,此时,如果直接通过this得到控件的句柄,然后对它进行操作是会抛异常的,.Net WinForm Application里面是不允许这样的操作的。这是,可以调用Invoke方法

2.Invoke方法签名:
object Control.Invoke(Delegate Method)
object Control.Invoke(Delegate Method, params object[] args)

3.使用自定义委托

private void DoWork() {
            WaitCallback wc 
= new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, 
"Guozhijian");
}


private delegate void MyInvokeDelegate(string name);

private void DoSomething(object o) {
            
this.Invoke(new MyInvokeDelegate(this.ChangeText), o.ToString());
}


private void ChangeText(string name) {
            
this.textBox1.Text = name;
}

4.使用System.Action:

private void DoWork() {
            WaitCallback wc 
= new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, 
"Guozhijian");
}


private void DoSomething(object o) {
            
this.Invoke(new Action<string>(this.ChangeText), o.ToString());
}


private void ChangeText(string name) {
            
this.textBox1.Text = name;
}

本例传递一个参数,System.Action有很多个重载,可以无参数(非泛型),而最多可以有四个参数,同样采用匿名方法,不使用泛型形式的System.Action,如下:

private void DoWork() {
            WaitCallback wc 
= new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, 
"Guozhijian");
}


private void DoSomething(object o) {
            this.Invoke(new Action(delegate() {
                
this.textBox1.Text = o.ToString();
            }
));
}

5.使用System.Func
如果Invoke调用主窗体操作之后,还希望在调用完得到一个返回值:

private void DoWork() {
            WaitCallback wc 
= new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, 
"Guozhijian");
}


private void DoSomething(object o) {
            System.Func
<stringint> f = new Func<stringint>(this.GetId);
            
object result = this.Invoke(f,o.ToString());
            MessageBox.Show(result.ToString());
}


private int GetId(string name) {
            
this.textBox1.Text = name;
            
if (name == "Guozhijian"{
                
return 999;
            }

            
else {
                
return 0;
            }

}

result的值为 999。
System.Func同样有很多泛形重载,这里不赘述。

6.关于Invoke的拥有者:Control
本文例中都是用this来引用,这里this替换为窗体任何一个控件的句柄都是OK的,因为Control.Invoke含义是将方法委托给拥有该Control的线程去执行。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
多线程
多线程
19 0
多线程面试题
本文章是自己总结的笔记,如有不对,请多指正,3Q
38 0
C#线程访问winform窗体控件
参考地址:http://www.cnblogs.com/jason-liu-blogs/archive/2012/09/08/2677008.html 添加: public Form() { InitializeComponent(); Control.
640 0
线程知识点
一、操作系统中线程和进程的概念 现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
998 0
多线程
多线程是程序员面试时常常会面对的问题,对多线程概念的掌握和理解水平,也会被一些老鸟用来衡量一个人的编程实力的重要参考指标。不论是实际工作需要还是为了应付面试,掌握多线程都是程序员职业生涯中一个必须经过的环节。
1269 0
+关注
醉意人间
喜欢GIS,喜欢将GIS技术在中国推广
412
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载