💈 A Cross-Thread Call Helper Class
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.
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.
The whole procedure of the test is recorded in figure 4. (The video lasts for 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\)
💈 A Cross-Thread Call Helper Class的更多相关文章
- update the UI property cross thread
this.Invoke((MethodInvoker)delegate { txtResult.Text = sbd.ToString(); // runs on UI thread });
- Flink - Checkpoint
Flink在流上最大的特点,就是引入全局snapshot, CheckpointCoordinator 做snapshot的核心组件为, CheckpointCoordinator /** * T ...
- [转]How to display the data read in DataReceived event handler of serialport
本文转自:https://stackoverflow.com/questions/11590945/how-to-display-the-data-read-in-datareceived-event ...
- c#子线程线程中操作窗体更新的报错
用 在执行上传时,由于操作较长窗体界面卡住,于是用task解决 Task t1 = new Task(manage.UploadData); t1.Start(); 结果不卡了,程序也传完了,运行到更 ...
- 进程创建过程详解 CreateProcess
转载请您注明出处:http://www.cnblogs.com/lsh123/p/7405796.html 0x01 CreateProcessW CreateProcess的使用有ANSI版本的Cr ...
- C#委托+回调详解
今天写不完,明天会接着写的,,,, 学习C#有一段时间了,不过C#的委托+回调才这两天才会用,以前只是知道怎么用.前面的一篇文章,函数指针,其实是为这个做铺垫的,说白了委托就相当于C语言中的函数指针, ...
- windows中的进程和线程
今天咱们就聊聊windows中的进程和线程 2016-09-30 在讨论windows下的进程和线程时,我们先回顾下通用操作系统的进程和线程.之所以称之为通用是因为一贯的本科或者其他教材都是这么说的: ...
- [MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))
对于稍微有点经验的.NET开发人员来说,倘若被问及如何保持线程同步,我想很多人都能说好好几种.在众多的线程同步的可选方式中,加锁无疑是最为常用的.如果仅仅是基于方法级别的线程同步,使用System.R ...
- Xamarin.Forms客户端第一版
Xamarin.Forms客户端第一版 作为TerminalMACS的一个子进程模块,目前完成第一版:读取展示手机基本信息.联系人信息.应用程序本地化. 功能简介 详细功能说明 关于TerminalM ...
- [源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块
[源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块 目录 [源码解析] 深度学习流水线并行 PipeDream(5)--- 通信模块 0x00 摘要 0x01 前言 0x02 ...
随机推荐
- 通过与Quickbuild和Mist.io的持续集成实现云管理和使用监控
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 这篇文章由巴拉克·梅里莫维奇撰写. 总结我自己有关Openstack的各种骚操作先告一段落.这一次我想谈谈有关监控云服务的使用情况. 我个人使用 ...
- linux unzip 解压后文件名乱码
在windows上zip的包,rz上传到linux下,发现出现乱码.记录下解决过程: 1.确定windows上的默认字符集 在Windows平台下,直接在命令行中,输入:chcp 在显示的结果中,会出 ...
- VMware虚拟机上建立HTTP服务步骤
1.使用xshell连接虚拟机,也可直接在虚拟机中敲命令. 以下是xshell上的命令: 首先安装HTTPD包 [root@one ~]# mount /dev/sr0 /mnt[root@one ~ ...
- 改变UITableView选中行高亮的颜色
UIView *backView = [[UIView alloc] initWithFrame:self.contentView.frame]; backView.backgroundColor = ...
- iOS UImage 与 RGB 裸数据的相互转换
iOS UImage 与 RGB 裸数据的相互转换 Touch the data of image in iOS Get data from a image 较简单,根据已有的 image 的属性,创 ...
- Python程序的执行方式
Python代码有两种执行方式: 一.文件执行 二.交互器执行(推荐) 一.文件执行 1.用 notepad++ 或 Sublime Text,甚至 写字本创建一个文件. 2.比如:print('He ...
- 04_Javascript初步第二天(下)
错误对象 try{ aa();//这是一个未被定义的方法 }catch(e){ alert(e.name+":"+e.message);//输出:ReferenceError:aa ...
- java根据模板导出pdf
在网上看了一些Java生成pdf文件的,写的有点乱,有的不支持写入中文字体,有的不支持模板,有的只是随便把数据放里面生成文件,完全不考虑数据怎样放置的以及以后的维护性,想想还是自己总结一个完全版的导出 ...
- java 多维数组遍历
java 多维数组遍历的顺序的性能问题 ps:下图为java多维数组内存分布原理.出自:http://math.hws.edu/javanotes/c7/two-dimensional-array.p ...
- 查看Eclipse运行工程时使用的Command Line
一.查看使用的Command Line 1.Window -> Show View -> Other... -> Debug 2.运行工程,然后在Debug视窗中找到运行的工程的主线 ...