标签:Winform,跨线程,访问,UI元素
在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应, 同时我们又需要在工作线程中更新UI界面上的控件。但直接访问会出现“线程间操作无效”的情况,因为.NET禁止了跨线程调用控件, 否则谁都可以操作控件,最后可能造成错误。 下面介绍几种跨线程访问的方法:
1、禁止对跨线程访问做检查 (不推荐使用这种方法)
这种方法不检查跨线程访问,允许各个线程操作UI元素,容易出现错误。
public Form2()
{
InitializeComponent();
//禁止对跨线程访问做检查 (不推荐使用这种方法)
Control.CheckForIllegalCrossThreadCalls = false;
}
2、使用委托方法 将其委托给UI控件更新
//使用委托方法 将其委托给UI控件更新
private void button1_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();
}
}
3、使用delegate和BeginInvoke来从其他线程中控制控件
只要把上面的 this.label2.Invoke(actionDelegate, str); 中的 Invoke 改为BeginInvoke方法就可以了。
Invoke方法和BeginInvoke方法的区别是:Invoke方法是同步的, 它会等待工作线程完成,BeginInvoke方法是异步的, 它会另起一个线程去完成工作线。
4、使用同步上下文:SynchronizationContext方法
该方法是取得主线程的上下文信息,然后在子线程将访问UI控件方法推送到UI上下文的消息队列里,使用POST或者Send;
private SynchronizationContext synchronizationContext;
private void button2_Click(object sender, EventArgs e)
{
synchronizationContext = SynchronizationContext.Current;
new Thread(() => { UpdateText("跨线程访问"); }).Start();
}
void UpdateText(string msg)
{
synchronizationContext.Post(_ => this.label2.Text = msg, null);
}
5、使用BackgroundWorker组件(推荐使用这个方法)
BackgroundWorker是.NET里面用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。耗时的操作(如下载和数据库事务)。
public partial class FileManagerForm : Form
{
FileInfo file ;
BackgroundWorker bw;
ServerFile server;
public FileManagerForm(string filePath)
{
InitializeComponent();
file = new FileInfo(filePath);
long size = file.Length / 1024 / 1024;
lblOrgSize.Text = (int)size+ "MB";
bw = new BackgroundWorker();
server = new ServerFile(file.Name);
}
private void FileManagerForm_Load(object sender, EventArgs e)
{
proUpFile.Minimum = 0;
proUpFile.Maximum = 100;
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += Bw_DoWork;
bw.ProgressChanged += Bw_ProgressChanged;
bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
bw.RunWorkerAsync();
}
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
using(FileStream fileRead= file.OpenRead())
{
long setp = file.Length / 100;
while (file.Length > fileRead.Position)
{
if (bw.CancellationPending)
{
break;
}
byte[] bytes = new byte[1024];
int count = fileRead.Read(bytes, 0, bytes.Length);
long writeLength= server.UpFile(bytes, count);
if(writeLength >proUpFile.Value* setp)
{
int size = (int)(writeLength / 1024 / 1024);
bw.ReportProgress(proUpFile.Value + 1, size);
}
}
server.Close();
}
}
private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
proUpFile.Value= e.ProgressPercentage> proUpFile.Maximum?proUpFile.Maximum:e.ProgressPercentage;
lblUpLoadSize.Text = e.UserState.ToString() + "MB";
}
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (this.proUpFile.Value == this.proUpFile.Maximum)
{
MessageBox.Show("文件发送成功!");
}
else
{
MessageBox.Show("文件发送失败!");
}
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
bw.CancelAsync();
}
}
来源:https://www.cnblogs.com/pilgrim/p/12875063.html


猜你喜欢
- 多线程@Async的使用体验场景导入:可以将大批量的数据insert操作采用多线程的方式并行执行第三方服务的接口调用:由于存在个别第三方服务
- public static String toUtf8String(String s) {
- 本文实例为大家分享了C语言实现稀疏矩阵的具体代码,供大家参考,具体内容如下#include "stdio.h"#defi
- 前言本文主要给大家介绍了关于Spring中@Scheduled和HttpClient的坑,分享出来供大家参考学习,下面话不多说了,来一起看看
- isInstance和isAssignableFromobj instanceof Class判断obj是不是Class或者Class的子类
- 发现问题最近工作中利用JNA 调用 dll 库时保错,错误如下:///////////////// 通过 JNA 引入 DLL 库 ////
- Thumbnailator 是一个优秀的图片处理的Google开源Java类库。处理效果远比Java API的好。从API提供现有的图像文件
- 错误表现如下图示,这两处可能报错发生原因一个pom文件里面,只能有有一对denpendencies标签,所有的配置都要放入这个depende
- 锁是个非常有用的工具,运用场景非常多,因为它使用起来非常简单,而且易于理解。但同时它也会带来一些困扰,那就是可能会引起死锁,一旦产生死锁,就
- js和python是两种语言,js处理网页数据,python可作为服务端开发,两者通过websocket进行通信。websocket是soc
- 首先在命令行创建一个PhoneGap工程phonegap create . "jspdf.sample" "J
- webflux过滤器(RouterFunction实现)相关类与接口HandlerFiterFunction@FunctionalInter
- 1.Fork/Join框架简介Fork/Join 它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并
- 本文实例为大家分享了java实现webservice方式的具体代码,供大家参考,具体内容如下经过测试 jdk1.6.10以下会出现bug 建
- @EqualsAndHashCode注解@EqualsAndHashCode注解的作用就是自动实现model类的equals方法和hashc
- 一、在GitHub上创建一个OAuth二、OAuth的原理Spring官方文档三、OkHttp的使用OkHttp官方网站1.Post代码示例
- 方式一public class Test{ public static void main(String[] args) throws Ex
- Weblogic部署war找不到spring配置文件我有一个web工程在Tomcat7下部署没有问题,可是移植到Weblogic10上出现如
- 相应的类库可在我的资源页面中找到,关于类成员的说明可通过对象浏览器查看函数说明Imports BitOperatorLibrary.Shif
- 前言坚持是一件比较难的事,坚持并不是自欺欺人的一种自我麻痹和安慰,也不是做给被人的,我觉得,坚持的本质并没有带着过多的功利主义,如果满是功利