C# 跨线程呼叫控制
在C# 应用程序开发, 我们经常要UI作线程分开,防止界面停止响应。 同一时候我们又须要在工作线程中更新UI界面上的控件,
以下介绍几种经常使用的方法
阅读文件夹
- 线程间操作无效
- 第一种办法:禁止编译器对跨线程訪问做检查
- 另外一种办法: 使用delegate和invoke来从其它线程中调用控件
- 第三种办法: 使用delegate和BeginInvoke来从其它线程中控制控件
- 第四种办法: 使用BackgroundWorker组件
- 源码下载
线程间操作无效
界面上有一个button和一个label, 点击button会启动一个线程来更新Label的值

- private void button1_Click(object sender, EventArgs e)
- {
- Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
- thread1.Start("更新Label");
- }
- private void UpdateLabel(object str)
- {
- this.label1.Text = str.ToString();
- }

执行后。 程序会报错 "跨线程操作无效,从不是创建"label1"的线程訪问它"
这是由于.NET禁止了跨线程调用控件。 否则谁都能够操作控件,最后可能造成错误。
以下介绍几种跨线程调用控件的方法
第一种办法:禁止编译器对跨线程訪问做检查
这是最简单的办法, 相当于不检查线程之间的冲突。同意各个线程随便乱搞,最后Lable1控件的值是什么就难以预料了 (不推荐使用这样的方法)
- public Form1()
- {
- InitializeComponent();
- // 增加这行
- Control.CheckForIllegalCrossThreadCalls = false;
- }
另外一种办法: 使用delegate和invoke来从其它线程中调用控件
调用控件的invoke方法。就能够控制控件了,比如

- private void button2_Click(object sender, EventArgs e)
- {
- Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
- thread1.Start("更新Label");
- }
- private void UpdateLabel2(object str)
- {
- if (label2.InvokeRequired)
- {
- // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想訪问它
- Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
- // 或者
- // Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
- this.label2.Invoke(actionDelegate, str);
- }
- else
- {
- this.label2.Text = str.ToString();
- }
- }

第三种办法: 使用delegate和BeginInvoke来从其它线程中控制控件
仅仅要把上面的 this.label2.Invoke(actionDelegate, str); 中的 Invoke 改为BeginInvoke方法就能够了
Invoke方法和BeginInvoke方法的差别是
Invoke方法是同步的, 它会等待工作线程完毕。
BeginInvoke方法是异步的, 它会另起一个线程去完毕工作线程
第四种办法: 使用BackgroundWorker组件(推荐使用这种方法)
BackgroundWorker是.NET里面用来运行多线程任务的控件。它同意编程者在一个单独的线程上运行一些操作。耗时的操作(例如以下载和数据库事务)。
使用方法简单

- private void button4_Click(object sender, EventArgs e)
- {
- using (BackgroundWorker bw = new BackgroundWorker())
- {
- bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
- bw.DoWork += new DoWorkEventHandler(bw_DoWork);
- bw.RunWorkerAsync("Tank");
- }
- }
- void bw_DoWork(object sender, DoWorkEventArgs e)
- {
- // 这里是后台线程, 是在还有一个线程上完毕的
- // 这里是真正做事的工作线程
- // 能够在这里做一些费时的。复杂的操作
- Thread.Sleep(5000);
- e.Result = e.Argument + "工作线程完毕";
- }
- void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- //这时后台线程已经完毕。并返回了主线程。所以能够直接使用UI控件了
- this.label4.Text = e.Result.ToString();
- }

版权声明:本文博客原创文章。博客,未经同意,不得转载。
C# 跨线程呼叫控制的更多相关文章
- [WinForm]WinForm跨线程UI操作常用控件类大全
前言 在C#开发的WinForm窗体程序开发的时候,经常会使用多线程处理一些比较耗时之类的操作.不过会有一个问题:就是涉及到跨线程操作UI元素. 相信才开始接触的人一定会遇上这个问题. 为了解决这个问 ...
- c#中多线程同步Lock(锁)的研究以及跨线程UI的操作
本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做demo的时候,就把多线程通过事件操作UI的代码也写了出来,留作备忘和分享吧. 其实多线程的同步,使用 ...
- winform 跨线程操作控件
当进行winform的开发时,经常遇到用时比较久的操作,在传统的单线程程序中,用户必须等待这个耗时操作完成以后才能进行下一步的操作,这个时候,多线程编程就派上用场了,将这个耗时的操作放到一个新的子线程 ...
- 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常
在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...
- c#跨线程访问控件帮助类
1.背景 对于winform程序来说,当我们点击按钮,需要消耗一定时长才能拿到数据后才能显示在界面上某个控件上的情况,我们通常会专门开一个线程去拿数据,这样不会造成界面处于假死状态 2.常规做法 // ...
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
- C#跨线程操作控件
1.首先通过按键创建子线程: 创建子线程,子线程调用changeText方法. private void btnOK_Click(object sender, EventArgs e) { Threa ...
- 简短总结一下C#里跨线程更新UI(转)
摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...
- C# 跨线程调用控件
在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应. 同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁 ...
随机推荐
- 数据结构 - AVL木
在计算机科学,AVL木是一个平衡树最早发明. 于AVL树节点,而不管是什么的两个子树之一的高度之间最大的区别,因此,它也被称为平衡树高.查找.O(log n). 插入和移除可能需要一个或更多次通过旋转 ...
- redis(Remote Dictionary Server)
redis的简介和使用 简介 redis(Remote Dictionary Server)是一种Nosql技术,它是一个开源的高级kv存储和数据结构存储系统,它经常被拿来和Memcached相比 ...
- Hadoop处理HDF文件
1.前言 HDF文件是遥感应用中一种常见的数据格式,因为其高度结构化的特点,笔者曾被怎样使用Hadoop处理HDF文件这个问题困扰过相当长的一段时间.于是Google各种解决方式,但都没有找到一种理想 ...
- nyist 488 素数环(搜索+回溯)
素数环 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描写叙述 有一个整数n,把从1到n的数字无反复的排列成环,且使每相邻两个数(包含首尾)的和都为素数,称为素数环. ...
- StackExchange.Redis 使用 (一)
在StackExchange.Redis中最重要的对象是ConnectionMultiplexer类, 它存在于StackExchange.Redis命名空间中.这个类隐藏了Redis服务的操作细节, ...
- 使用js在新窗口中POST数据
最近在做自己的博客,写文章的时候有一个预览功能,当时使用的是弹出框来进行预览,感觉体验不是很好. 然后想到了写邮件时候的新窗口预览,查了下126邮箱和qq邮箱的预览实现效果,以及各种谷歌百度stack ...
- 为什么在Python3.4.1里输入print 10000L或10000L失败
打开Python的命令行交互窗体,而且在里面进行以下的输入: Python 3.4.1 (v3.4.1:c0e311e010fc, May 18 2014, 10:38:22) [MSC v.1600 ...
- Unity3d C# Socket 下载文件 (同步到)
续篇 Unity3d C# HttpWebRequest 异步下载文件 ,由于project编译为IL2CPP的情况下仍然无效.提示HttpWebrequest 在当前版本号不支持.所以还是寻求其他的 ...
- ehcache历史变迁及常用API的使用(转)
ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案.同时ehcache作为开放源 ...
- 了解大数据的技术生态系统 Hadoop,hive,spark(转载)
首先给出原文链接: 原文链接 大数据本身是一个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你能够把它比作一个厨房所以须要的各种工具. 锅碗瓢盆,各 ...