在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来。一个最直接的方法便是使用多线程。多线程编程的方式在WinForm开发中必不可少。
本文介绍在WinForm开发中如何使用多线程,以及在线程中如何通过Control.Invoke方法返回窗体主线程执行相关操作。

-. WinForm多线程编程
1. new Thread()

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

privatevoid DoWork() {
 Thread t =new Thread(new ThreadStart(this.DoSomething));
 t.Start();
 }
private void DoSomething() {
 MessageBox.Show("thread start");
 }

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

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

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

privatevoid DoWork(){
 ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething));
 }
private void DoSomething(object o) {
 MessageBox.Show("thread start");
 }

有参数传递:

privatevoid DoWork() {
 ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething),"guozhijian");
 }
private void DoSomething(object o) {
 MessageBox.Show(o.ToString());
 }

使用匿名方法更灵活:

privatevoid 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.使用自定义委托

privatevoid 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:

privatevoid 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,如下:

privatevoid 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调用主窗体操作之后,还希望在调用完得到一个返回值:

privatevoid 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 999;
 }
else {
return 0;
 }
 }

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

6.关于Invoke的拥有者:Control

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

转载:http://www.cnblogs.com/ghfsusan/archive/2011/12/28/2304310.html

转载于:https://www.cnblogs.com/aiwz/p/6153924.html

浅述WinForm多线程编程与Control.Invoke的应用相关推荐

  1. < 今日份知识点: 浅述对函数式编程的理解 及其 优缺点 >

    文章目录 前言

  2. 使用control.invoke返回当前窗口线程[转]

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

  3. WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C

    WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用.但可以通过 invoke 来保证 Con ...

  4. Control.Invoke和Control.BeginInvoke

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

  5. 在.Net中进行跨线程的控件操作(上篇:Control.Invoke)

    本文的重点在于介绍如何在多线程编程中,从非UI线程上访问界面中的控件.有过多线程编程经验的人都知道,当我们在非UI线程上试图给一个界面中的控件赋值的时候,比如说label的Text属性,系统会抛出一个 ...

  6. .Net开发中的多线程编程总结

    微软.Net开发中的多线程编程进行一个简单的总结,相信对大家会有所帮助的.下面就具体来看看: 不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: T ...

  7. 微软.Net开发中的多线程编程总结

    不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: ThreadStart threadStart=new ThreadStart(Calculat ...

  8. 面试归来——梳理社招面试以及浅述对程序员职业生涯的看法

    原谅我是一个后知后觉的人,已经在新的岗位工作了两个月,才写这篇文章. 本文会先讲述博主一个月的面试经历,梳理一下技术面试,浅述关于程序员职业生涯的一些看法. 从创业到再就业 大概4个月以前,终止创业已 ...

  9. (C#)安全、简单的Windows Forms多线程编程 (一)

    (C#)安全.简单的Windows Forms多线程编程  (一) Chris Sells June 28, 2002 翻译:袁晓辉 www.farproc.com farproc#AT#gmail# ...

最新文章

  1. CloudCompare的介绍
  2. php写js跳转页面,php实现页面的三种跳转
  3. 大块数据申请及DMA
  4. 软件测试的复杂性与经济性
  5. Java为啥不建议用通配符_为什么在Java导入语句中使用通配符不好?
  6. 供配电负荷计算方法详解
  7. 对自己有用的VS调试技巧
  8. Android Handler处理机制 ( 三 ) ——Handler,Message,Looper,MessageQueue
  9. to_csvread_csvisnullisnanisna
  10. linux 中文乱码 转png_使用pdfBox实现pdf转图片,解决中文方块乱码等问题
  11. TensorFlow精进之路(一):Softmax回归模型训练MNIST
  12. C#中的方法(函数),委托和事件
  13. VC++ 6.0 C8051F340 USB 通信 CAN 数据解析
  14. ARM Cortex-A53 Cache与内存的映射关系以及Cache的一致性分析
  15. RapidShare 真实链接抓取助手
  16. MT【133】磨刀不误砍柴工
  17. websocket握手失败_WebSocket通信之握手协议
  18. 上半年计算机二级试题,2016上半年计算机二级模拟题及答案
  19. 通过宏快速破解EXCEL文件密码
  20. 估计量的无偏性,有效性和一致性

热门文章

  1. koa --- 跨域,解析POST参数、路由配置
  2. css --- 应用媒介查询制作响应式导航栏
  3. MDN文档基础知识搜集
  4. 正整数分解为几个连续自然数之和
  5. Python 生成器 迭代器
  6. sass 安装配置和使用
  7. bundlefusion论文阅读笔记
  8. html后台数据分类管理,细分数据.html
  9. 杀死应用进程 android,如何杀死Android应用程序启动的logcat进程?
  10. 2019牛客暑期多校训练营(第一场) - B - Integration - 数学