博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用
阅读量:6693 次
发布时间:2019-06-25

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

Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 Control 线程安全。

在跨线程更新的时候,Control 会检查 CurrentThread 是否为创建 Control 的线程,并报错!

示例代码如下:

复制代码
ExpandedBlockStart.gif
示例代码
private
void btnStart_Click(
object sender, EventArgs e)
{
//
注意:特地不使用 Timer 控件
Thread thread =
new Thread(Fun);
thread.Start(DateTime.Now.ToString());
}
//
报错:线程间操作无效: 从不是创建控件“lblTime”的线程访问它。
private
void Fun(
object datetime)
{
lblTime.Text = (
string)datetime;
}
复制代码

最简单的解决方式是在程序代码中添加如下属性:

Control.CheckForIllegalCrossThreadCalls = false;

在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。

将要做的事情放在工作线程中执行,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的。

使用 BeginInvoke 方法解决该问题的代码如下:

复制代码
ExpandedBlockStart.gif
使用BeginInvoke方法
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Invoke_Test
{
public
partial
class Form1 : Form
{
//
private System.Windows.Forms.Label lblTime;
//
private System.Windows.Forms.Button btnStart;
public Form1()
{
InitializeComponent();
//
解决方式一
//
Control.CheckForIllegalCrossThreadCalls = false;
}
private
void btnStart_Click(
object sender, EventArgs e)
{
string arg = DateTime.Now.ToString();
//
注意:创建子线程间接调用
Thread thread =
new Thread(FunStart);
thread.Start(arg);
//
arg 给方法传参
}
//
定义调用方法的委托
delegate
string FunDelegate(
string str);
//
注意:特地使用 FunStart 方法模拟间接调用
private
void FunStart(
object obj)
{
//
要调用的方法的委托
FunDelegate funDelegate =
new FunDelegate(Fun);
/*
========================================================
* 使用this.BeginInvoke方法
* (也可以使用this.Invoke()方法)
========================================================
*/
//
this.BeginInvoke(被调用的方法的委托,要传递的参数[Object数组])
IAsyncResult aResult =
this.BeginInvoke(funDelegate,obj.ToString());
//
用于等待异步操作完成(-1表示无限期等待)
aResult.AsyncWaitHandle.WaitOne(-
1);
//
使用this.EndInvoke方法获得返回值
string str = (
string)
this.EndInvoke(aResult);
MessageBox.Show(str.ToString());
}
//
真正需要执行的方法
private
string Fun(
string datetime)
{
lblTime.Text = (
string)datetime;
return
"
委托的返回值
";
}
}
}
复制代码

Control.InvokeRequired 属性:当前线程不是创建控件的线程时为 true。

也可以认为,在 new Control() 的时候,Control 用一个变量记录下了当前线程,在调用 InvokeRequired 时,返回当前线程是否不等于 new 的时候记录下来的那个线程。

Control.Invoke 和 Control.BeginInvoke 就是“发短信”的方法,如果使用 Control.Invoke 发短信,那么甲线程就会像个痴情的汉子,一直等待着乙线程的回音,而如果使用 Control.BeginInvoke 发送短信,那发完短信后,甲线程就会忙活自己的,等乙线程处理完再来瞧瞧。

本文转自钢钢博客园博客,原文链接:http://www.cnblogs.com/xugang/archive/2010/06/05/1752235.html,如需转载请自行联系原作者

你可能感兴趣的文章
服务器配置之DNS服务器
查看>>
PHP适配器模式
查看>>
性能测试工具sysbench简介
查看>>
网络综合测试--5
查看>>
Centos 6.5 离线安装包下载地址
查看>>
字符串相似度
查看>>
CMAKE方式编译安装Mysql5.5
查看>>
日志服务器管理网络设备日志(Cisco;华为;f5;netscreen;)
查看>>
统计单词个数
查看>>
springcloud中配置服务actuator的小坑
查看>>
ListviewFilter
查看>>
MyBatis Eclipse插件安装
查看>>
机器学习中的回归理解
查看>>
再学 GDI+[4]: DrawEllipse - 绘制椭圆
查看>>
kUbuntu 13.04安装搜狗输入法
查看>>
笔记本水货的辨别方法
查看>>
准备理一下菜单和工具栏相关的组件
查看>>
电商网站购买流程的一些思考(注册、一键购买、会员激励)
查看>>
python 操作 xml
查看>>
redhat/centos使用service控制启动与关闭
查看>>