在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<string, int> f = new Func<string, int>(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 ;
}
else {
return ;
}
}

  result的值为 999。

  System.Func同样有很多泛形重载,这里不赘述。

  6.关于Invoke的拥有者:Control

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

  

WinForm多线程编程与Control.Invoke的应用浅谈的更多相关文章

  1. 浅述WinForm多线程编程与Control.Invoke的应用

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

  2. 【转】浅述WinForm多线程编程与Control.Invoke的应用

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

  3. WinForm多线程编程简单Demo

    需要搭建一个可以监控报告生成的CS(WinForm)工具,即CS不断Run,执行获取数据生成报告,经过研究和实践,选择了使用"WinForm多线程编程"的解决方案.当然参考了园中相 ...

  4. winform 多线程编程

    参考资料: WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件) c# 使用定时器Timer

  5. C#多线程编程总结

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

  6. WinForm多线程学习文档

    基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程W ...

  7. C# WinForm多线程(三)Control.Invoke

    下面我们就把在Windows Form软件中使用Invoke时的多线程要注意的问题给大家做一个介绍. 首先,什么样的操作需要考虑使用多线程?总的一条就是,负责与用户交互的线程(以下简称为UI线程)应该 ...

  8. WinForm二三事(三)Control.Invoke&Control.BeginInvoke

    http://www.cnblogs.com/yuyijq/archive/2010/01/11/1643802.html 这个系列从2009年写到2010年,差点又成太监文.随着WPF/Silver ...

  9. Control.Invoke和Control.BeginInvoke

    问题的引入 下面有个简单的demo,大家一看代码就知道效果如何示例.我新建一个winform的程序,然后写入了如下代码: using System; using System.Windows.Form ...

随机推荐

  1. Angular 4.0 环境搭建

    1.安装node 2.angular cli安装 sudo npm install -g @angular/cli 3. 使用ng -v 查看安装结果 4. 创建项目 ng new helloworl ...

  2. zufeoj Electrification Plan (最小生成树,巧妙设e[i][j]=0)

    Electrification Plan 时间限制: 1 Sec  内存限制: 128 MB提交: 31  解决: 13[提交][状态][讨论版] 题目描述 Some country has n ci ...

  3. PHP简单查询界面

    <html> <style type='text/css'> table {border-collapse:collapse;} td {border:solid 1px #d ...

  4. 共享存储(ISCSI网络存储)

    server端:(192.168.100.11) 分区sdb 分别为10G和5G #fdisk /dev/dab …… 同步分区表 #partprobe /dev/sdb # yum install ...

  5. IntelliJ IDEA 创建Web项目

    1:创建Project:依次点击File–new Project: 2:选择Empty Project项目,点击Next: 3:输入项目名称,选择项目路径: 4:创建Module:点击Finish,弹 ...

  6. eclipse离线安装Activiti Designer插件

    提供下载的链接:https://download.csdn.net/download/qq_41436774/10437391 1.打开Eclipse,点击Help ---> Install n ...

  7. SonarQube

    代码质量管理 Sonar 是一个用于代码质量管理的开放平台.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson/Jenkins 等)不 ...

  8. while_else

    使用while循环输出100-50,从大到小,到50的时候,再从0到50输出,然后结束count =

  9. SQL Server占用服务器内存过高

    SQL Server对服务器内存的使用策略是用多少内存就占用多少内存,只用在服务器内存不足时,才会释放一点占用的内存,所以SQL Server 服务器内存往往会占用很高. 查看内存状态: DBCC M ...

  10. Python预编译语句防止SQL注入

    这个月太忙,最近不太太平,我的愿望是世界和平! ================================== 今天也在找python的预编译,早上写的sql是拼接来构成的.于是找了2篇文章,还 ...