惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - antony.net

移动版网页自动缩放问题 2011年国内五款值得关注网店系统 Enterprise Architect 7 入门教程大全 Enterprise Architect 业务过程建模 不同浏览器处理后退的一些异同 - antony.net - 博客园 23个.NET开源项目 mysql 存储过程 游标 js代码库 table css 固定表头 - antony.net Hash Tables in Javascript RSClientPrint打印 统计sql语句 文档格式批量转换(doc,txt,pdf等) 了解HTTP Headers的方方面面 XmlSerializer 常见问题疑难解答 webservices 水晶报表 - antony.net - 博客园 Build a Custom RadioButton Cell and Column for the DataGridView Control .NET 2.0 - WinForm Control - DataGridView 编程36计(二)
在非UI线程中改变UI控件属性的通用方法
antony.net · 2010-10-10 · via 博客园 - antony.net

转自:http://www.sunnychen.org/trackback.asp?tbID=124&action=addtb&tbKey=43c0d85c8d6d5dcc018d174276ac098da9245500

在.NET中如需在非UI线程中改变UI控件属性时,CLR会抛出异常,提示无法在非UI线程中更新界面上的控件(Cross-thread operation not valid)。一般情况下有两种解决办法。第一种就是设置Control的静态属性CheckForIllegalCrossThreadCalls为False,如下:

03     InitializeComponent();
04     Control.CheckForIllegalCrossThreadCalls = false;
07 private void button1_Click(object sender, EventArgs e)
09     Thread thread = new Thread(() =>
11         for (int i = 0; i < 100000; i++)
13             label1.Text = i.ToString();
14             label1.Refresh();

另一种办法,就是使用委托,根据控件的InvokeRequired属性判断当前控件的更新操作是否是在另一个线程中。如果是,则使用委托进行方法调用并更新控件。但是这种方法有个缺点,就是需要针对每个控件的属性设置方式创建一些单独的委托和方法,这些委托和方法仅仅是在解决跨线程操作的时候使用。比如,你在另一个线程中需要修改某个label的text时,你就需要创建一个SetLabelText方法,假设你还需要更新TextBox的text,那么你还需要另外创建一个SetTextBoxText方法。

通过下面的委托和方法的定义,我们实现了“一次定义,多次使用”。请看:

01 private delegate void ParameterizedControlUpdate(params object[] args);
03 private delegate void ControlUpdateDelegate(Component c,
04     ParameterizedControlUpdate callback,
05     params object[] args);
07 private void DelegatedControlUpdate(Component c,
08     ParameterizedControlUpdate callback,
09     params object[] args)
11     Control target = (c is Control) ? (c as Control) : this;
12     if (target.InvokeRequired)
14         ControlUpdateDelegate d = DelegatedControlUpdate;
15         target.Invoke(d, new object[] { c, callback, args });
19         callback(args);

于是,上面的例子可以改为:

01 private void button1_Click(object sender, EventArgs e)
03     Thread thread = new Thread(() =>
05         for (int i = 0; i < 100000; i++)
07             DelegatedControlUpdate(label1, args =>
09                     label1.Text = (string)args[0];
10                     label1.Refresh();
11                 }, i.ToString());