当前位置: 首页 > news >正文

【C#】多线程中,跨线程实现对UI控件更新

问题描述:

“Cross-thread operation not valid :Control ‘listBox1’ accessed from a thread other than the thread it was created on” ,即“线程间操作无效,从不是创建控件“listbox1”的线程访问它。”

原因分析:

UI控件 不是线程安全的,UI控件的设计是仅由创建它们的UI线程进行操作。

解决思路:

解决方法有好几种,这里只介绍 自认为最好的方法:子线程类中建立委托事件,子线程调用事件,具体事件的实现在UI线程中实现。

解决方法示例:

1. 第一步 新建一个消息类

在本类中只包含一个变量:String Message。
实际项目中可以扩展很多变量,比如线程是否即将结束标识、线程已经处理任务的数目等等。

	//消息类,public class MessageEventArgs : EventArgs{public String Message; //消息。public MessageEventArgs(string message){this.Message = message;}}

2. 第二步 新建一个子线程类:

 class SubThread{/// <summary>///  消息委托(题外话,delegate(委托)太形象了,把消息内容委托给 主程序的方法去绑定显示。/// </summary>/// <param name="sender">委托的发送者,在这里就是SubThread的对象</param>/// <param name="e">委托者发送的信息</param>public delegate void MessageEventHandler(object sender, MessageEventArgs e);//定义事件public event MessageEventHandler MessageSend;/** 说明:定义事件处理函数,当然这里也可以不用直接在引发事件时调用this.MessageSend(sender, e);* 这里的参数要和事件代理的参数一样* */public void OnMessageSend(object sender, MessageEventArgs e){if (MessageSend != null)this.MessageSend(sender, e);}//定义一个线程public System.Threading.Thread sendthread;/// <summary>/// 线程的方法/// </summary>private void UploadTest(){try{for (int i = 0; i < 5; i++){System.Threading.Thread.Sleep(1000); //这里让线程睡眠,模拟长时间执行的任务this.OnMessageSend(this, new MessageEventArgs(DateTime.Now.ToString()+" "+(i+1)+"号文件上传成功!"));}}catch{}}//线程启动public void StartUpload(){sendthread = new System.Threading.Thread(new System.Threading.ThreadStart(UploadTest));sendthread.Start();}}

3. 第三步 新建一个Form

form中新建一个按钮,一个listBox,如下:
在这里插入图片描述
代码:
在主界面类中 的 private void subthread_MessageSend(object sender, MessageEventArgs e)种调用了一个
**Invoke()**的方法,此方法就是可以将 子线程传递过来的message 通过UI线程更新到 listbox1.

 public partial class Form1 : Form{SubThread subThread;public Form1(){InitializeComponent();subThread = new SubThread();subThread.MessageSend += new SubThread.MessageEventHandler(subthread_MessageSend);}//绑定public void ListBoxAdd(Object sender,MessageEventArgs msg){listBox1.Items.Add(msg.Message);}public delegate void MessageHandler(Object sender, MessageEventArgs e); //自定义一个委托类型.如果使用系统自带的Action,就无需定义此委托private void subthread_MessageSend(object sender, MessageEventArgs e){//方式一: 使用自定义的委托,将ListAdd赋值给自定位委托;//实例化委托MessageHandler handler = new MessageHandler(ListBoxAdd);  //不使用自定义的委托也行,使用Action//调用Invokethis.Invoke(handler, sender, e); //让主线程调用ListAdd函数,参数为子线程传递的信息方式二: 使用系统自带的委托类型Action //Action<object, MessageEventArgs> action = ListBoxAdd;        //使用系统自带的Action委托//this.Invoke(action, sender, e);}private void button1_Click(object sender, EventArgs e){subThread.StartUpload();}}

运行结果

在这里插入图片描述

相关文章:

  • 【并发程序设计】15.信号灯(信号量)
  • 企业百度百科词条怎么修改
  • Python 将Word、Excel、PDF、PPT文档转为OFD文档
  • 使用老毛桃制作USB安装盘并安装WIN10系统完整过程
  • 基于SpringBoot+Vue租房网站设计和实现(源码+LW+部署文档+讲解等)
  • 德国RS SMA100A原装二手sma100a信号发生器6G
  • Springboot校园美食推荐系统的开发-计算机毕业设计源码44555
  • 【Java面试】七、SpringMvc的执行流程、SpringBoot自动装配原理
  • docker 启动关闭,设置仓库地址
  • USB - ACK、NAK和STALL的含义
  • Android ANR Trace日志阅读分析技巧
  • STM32-14-FSMC_LCD
  • 2024年5月架构试题
  • 【C++ ——— 继承】
  • 关于MES管理系统七个维度的核心价值
  • IDEA常用插件整理
  • Java反射-动态类加载和重新加载
  • js ES6 求数组的交集,并集,还有差集
  • Solarized Scheme
  • Vue2.0 实现互斥
  • Vultr 教程目录
  • 动态规划入门(以爬楼梯为例)
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 力扣(LeetCode)965
  • 聊聊hikari连接池的leakDetectionThreshold
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前端工程化(Gulp、Webpack)-webpack
  • 手机端车牌号码键盘的vue组件
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 06-01 点餐小程序前台界面搭建
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (二开)Flink 修改源码拓展 SQL 语法
  • (离散数学)逻辑连接词
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)iOS字体
  • .bashrc在哪里,alias妙用
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • .net生成的类,跨工程调用显示注释
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • []串口通信 零星笔记
  • [《百万宝贝》观后]To be or not to be?
  • [AIGC] 如何建立和优化你的工作流?
  • [Angularjs]ng-select和ng-options
  • [C# 开发技巧]实现属于自己的截图工具
  • [c++进阶(九)] STL之deque深度剖析
  • [CodeForces-759D]Bacterial Melee
  • [ios] IOS文件操作的两种方式:NSFileManager操作和流操作【转】
  • [Java][Liferay] File system in liferay
  • [LeeCode]-Divide Two Integers 不用乘除的除法运算
  • [LeetCode]—Implement strStr() 寻找子串匹配第一个位置 (KMP)