在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. vmware 安装 ios 苹果系统

    我用的系统是win10... 一.所需软件: 1.下载并安装VMware Workstation Pro 12 密码:7ybc和序列号 密码是:bwm0 2.下载unlocker 203(for OS ...

  2. phper必知必会(二)

    1.说说你对进程,线程以及协程的理解 进程:是系统进行资源分配和调度的基本单位,是基本操作系统结构的基础.进程是程序基本执行的实体.进程与进程之间是独立的,拥有完全独立的地址空间,进程的切换只发生在内 ...

  3. AIX6.1用g++安装Poco-1.6.1-all

    项目终于到了把程序往小型机上部署的阶段了.不得不说AIX真是让人恶心,一个Poco编译弄了我1周时间.网上根本没有相关的资料. 1. AIX下安装gcc/g++:在ftp://ftp.software ...

  4. java学习之路之javaSE基础1

    <h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用 ...

  5. javascript 获取视口的高度和宽度

    //获取视口的高度和宽度. function windowHeight() { var de = document.documentElement; return self.innerHeight|| ...

  6. scala学习之路一

    所谓学习,那么首先就先简单介绍一下scala吧 1.scala的介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. Scal ...

  7. table边框

    border-collapse 语法 border-collapse:separate | collapse | inherit 默认值:separate 取值 separate: 默认值.边框会被分 ...

  8. nginx的日志分析

    1.到NGINX把日志DOWN下来2.用命令cat xxxx.log | egrep '10/Jul/2015:01:[4-5]|2015-07-10 02:0[0-57]'>xxxx2.log ...

  9. Introducing Deep Reinforcement

    The manuscript of Deep Reinforcement Learning is available now! It makes significant improvements to ...

  10. windows挂载gluseter NFS卷

    windows下挂载gluster提供的NFS卷 服务器端的配置: 首先配置好NFS共享,找一台linux试一下,确保挂载成功.linux客户端执行:mount.nfs 10.33.70.20:tes ...