💈 线程间互访助手类 (EN)
Conmajia © 2012, 2018
Published on August 5th, 2012
Updated on February 2nd, 2019
Introduction
While working on background threads, you may encounter updating values of frontend GUI controls. Then you probably will face one particular problem: invalid operation between threads. As shown in figure 1, this issue throws an InvalidOperationException
. It occurs every time when accesses properties/methods from other threads but the one which owns them.

In .NET Framework, version 2.0 as I refer, every Control
class contains an InvokeRequired
property and an Invoke
method to accomplish cross-thread operations. Some typical call code is listed below.
public void DoWork() {
if (control.InvokeRequired) {
control.Invoke(DoWork);
}
else {
// do work
}
}
My Approach
I wrote a helper class InvokeHelper
which granted me the power to access assets between different threads. The class has 3 methods:
Invoke()
- to call methods of a control.
InvokeHelper.Invoke(<control>, "<method>"[, <param1>[,<param2>,...]]);
Get()
- to get properties of a control.
InvokeHelper.Get(<control>, "<property>");
Set()
- to set properties of a control.
InvokeHelper.Set(<control>, "<property>", <value>);
Demonstration
In the demo, I used a forever looping background thread (t
) to show how the InvokeHelper
helps threads to interact. Thread t
updates the frontend thread (the GUI) every 500 milliseconds.
Thread t;
private void button1_Click(object sender, EventArgs e) {
if(t == null) {
t = new Thread(multithread);
t.Start();
label4.Text = string.Format("Thread state:\n{0}", t.ThreadState.ToString());
}
}
public void DoWork(string msg) {
this.label3.Text = string.Format("Invoke method: {0}", msg);
}
int count = 0;
void multithread() {
while(true) {
InvokeHelper.Set(this.label1, "Text", string.Format("Set value: {0}", count));
InvokeHelper.Set(this.label1, "Tag", count);
string value = InvokeHelper.Get(this.label1, "Tag")
.ToString();
InvokeHelper.Set(this.label2, "Text", string.Format("Get value: {0}", value));
InvokeHelper.Invoke(this, "DoWork", value);
Thread.Sleep(500);
count++;
}
}
Results shown in animated figure 2. Obviously, the frontend is not blocked despite t
never stops.

InvokeHelper
Demonstration (animation)Other Approaches
There is a built-in option in the VisualStudio IDE that disables the cross-thread access check: CheckForIllegalCrossThreadCalls
. I found it slightly slower than my helper class. Figure 3 shows the test result.

CheckForIllegalCrossThreadCalls
The whole procedure of the test is recorded in figure 4. (The video lasts for 8'51")

CheckForIllegalCrossThreadCalls
(8'51")Appendix
Source code of the InvokeHelper
is listed below. Zipped .NET project files: Download
public class InvokeHelper {
private delegate object MethodInvoker(Control control, string methodName, params object[] args);
private delegate object PropertyGetInvoker(Control control, object noncontrol, string propertyName);
private delegate void PropertySetInvoker(Control control, object noncontrol, string propertyName, object value);
private static PropertyInfo GetPropertyInfo(Control control, object noncontrol, string propertyName) {
if (control != null && !string.IsNullOrEmpty(propertyName)) {
PropertyInfo pi = null;
Type t = null;
if (noncontrol != null) t = noncontrol.GetType();
else t = control.GetType();
pi = t.GetProperty(propertyName);
if (pi == null) throw new InvalidOperationException(string.Format("Can't find property {0} in {1}.", propertyName, t.ToString()));
return pi;
} else throw new ArgumentNullException("Invalid argument.");
}
public static object Invoke(Control control, string methodName, params object[] args) {
if (control != null && !string.IsNullOrEmpty(methodName))
if (control.InvokeRequired) return control.Invoke(new MethodInvoker(Invoke), control, methodName, args);
else {
MethodInfo mi = null;
if (args != null && args.Length > 0) {
Type[] types = new Type[args.Length];
for (int i = 0; i
References
- Sergiu Josan, Making Controls Thread-safely, May 2009
- vicoB, Extension of safeInvoke, July 2010
The End. \(\Box\)
💈 线程间互访助手类 (EN)的更多相关文章
- Java:多线程,使用同步锁(Lock)时利用Condition类实现线程间通信
如果程序不使用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能用wait().notify().notifyAll()方法进行线程 ...
- 并发工具类(四)线程间的交换数据 Exchanger
前言 JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...
- Java并发工具类之线程间数据交换工具Exchanger
Exchanger是一个用于线程间协做的工具类,主要用于线程间的数据交换.它提供了一个同步点,在这个同步点,两个线程可以彼此交换数据.两个线程通过exchange方法交换数据,如果一个线程执行exch ...
- Java并发工具类(四):线程间交换数据的Exchanger
简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法 ...
- Object类中wait带参方法和notifyAll方法和线程间通信
notifyAll方法: 进入到Timed_Waiting(计时等待)状态有两种方式: 1.sleep(long m)方法,在毫秒值结束之后,线程睡醒,进入到Runnable或BLocked状态 2. ...
- Object类中wait代餐方法和notifyAll方法和线程间通信
Object类中wait代餐方法和notifyAll方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 进入 ...
- Disruptor——一种可替代有界队列完成并发线程间数据交换的高性能解决方案
本文翻译自LMAX关于Disruptor的论文,同时加上一些自己的理解和标注.Disruptor是一个高效的线程间交换数据的基础组件,它使用栅栏(barrier)+序号(Sequencing)机制协调 ...
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...
- 线程间通信 GET POST
线程间通信有三种方法:NSThread GCD NSOperation 进程:操作系统里面每一个app就是一个进程. 一个进程里面可以包含多个线程,并且我们每一个app里面有且仅有一 ...
随机推荐
- BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法
BZOJ_4870_[Shoi2017]组合数问题_矩阵乘法 Description Input 第一行有四个整数 n, p, k, r,所有整数含义见问题描述. 1 ≤ n ≤ 10^9, 0 ≤ ...
- ABP入门系列目录——学习Abp框架之实操演练
ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WE ...
- 浅析一款扫描dom-xss的浏览器插件
目录 0x00 前言 0x01 浅析 0x00 前言 这款插件的名字叫 ra2-dom-xss-scanner,其作者刚好也是jsprime的开发者,后续有可能会继续跟进一下jsprime.这个ra2 ...
- Linux - 修改Cent OS系统的的hostname、配置DNS映射
目录 1 修改方式 2 扩展: 配置DNS映射 本篇文章中, 示例设计到的操作系统是CentOS 6.5. 1 修改方式 ① 命令hostname onepiece -- 运行后设置立即生效, 但要在 ...
- xamarin开发android收集的一些工具
xamarin开发android收集的一些工具 工欲善其事,必先利其器,从16年下半年开始做xamarin相关的开发,平时使用的一些工具和google插件给大家分享一下,都有下载地址,持续更新. Vi ...
- Python猫荐书系列:文也深度学习,理也深度学习
最近出了两件大新闻,相信大家可能有所耳闻. 我来当个播报员,给大家转述一下: 1.中国队在第 11 界罗马尼亚数学大师赛(RMM)中无缘金牌.该项赛事是三大国际赛事之一,被誉为中学奥数的最高难度.其中 ...
- shell-输入与输出<echo, read, cat, tee >
1. echo echo命令可以显示文本行或变量,或者吧字符串输入到文件. 用法:echo [option] string #[option]可选:-e ==>解析转移字符,(常用的\n & ...
- git程序多版本维护方案
目前所在公司开发的系统为一个基础版本(通用版)包含了行业内一些基础功能实现,后期根据不同厂家进行定制版的开发,考虑独立项目的话代码维护不太方便,并且如果通用版本有变动的话,其他定制版本也都需要进行变动 ...
- Web前后端分离
第一篇博客:见谅 用自己的通俗语言讲web工程的前后端分离: 只是从自己的角度去分析,我眼中的前后端分离(可能不对) 首先要明白我们服务器和浏览器之前传输和接受的是什么: 静态文件(html,css, ...
- GIS之家demo源代码咨询
GIS之家demo源代码咨询收费服务(希望对 webgis 新人有所帮助) GIS之家QQ群(采取QQ群入群收费模式): GIS之家001:296438295 需要入群的giser们,入群之前联系GI ...