聊透多线程编程-线程基础-3.C# Thread 如何从非UI线程直接更新UI元素
目录
1. 使用 Control.Invoke 或 Control.BeginInvoke(Windows Forms)
2. 使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke(WPF)
3. 使用 SynchronizationContext
桌面应用程序(如 Windows Forms 或 WPF)中,UI 操作必须由主线程(也称 UI 线程)执行。如果尝试从非 UI 线程直接更新 UI 元素,通常会引发异常或导致不可预测的行为。
Thread 类本身无法直接更新 UI,但可以通过以下方法将操作委托给 UI 线程来实现安全的 UI 更新。
1. 使用 Control.Invoke 或 Control.BeginInvoke(Windows Forms)
在 Windows Forms 应用程序中,可以使用 Control.Invoke 或 Control.BeginInvoke 方法将代码调度到 UI 线程。
示例代码:
using System;
using System.Reflection.Emit;
using System.Threading;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;class Program : Form
{private Button button;private Label label;public Program(){button = new Button { Text = "Start Thread", Dock = DockStyle.Top };label = new Label { Text = "Waiting...", Dock = DockStyle.Fill };button.Click += Button_Click;Controls.Add(label);Controls.Add(button);}private void Button_Click(object sender, EventArgs e){Thread thread = new Thread(UpdateLabel);thread.Start();}private void UpdateLabel(){for (int i = 0; i < 10; i++){// 检查是否需要调用 Invokeif (label.InvokeRequired){// 使用 Invoke 将操作调度到 UI 线程label.Invoke(new Action(() => label.Text = $"Count: {i}"));}else{// 如果当前线程是 UI 线程,则直接更新label.Text = $"Count: {i}";}Thread.Sleep(500); // 模拟工作}}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new Program());}
}
解释:
- InvokeRequired:检查当前线程是否是创建控件的线程(即 UI 线程)。如果不是,则需要通过 Invoke 或 BeginInvoke 调度到 UI 线程。
- Invoke:同步执行指定的操作,等待操作完成后再继续。
- BeginInvoke:异步执行指定的操作,不阻塞当前线程。
输出效果:
点击按钮后,label 的文本会每 500 毫秒更新一次,显示当前计数值。
2. 使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke(WPF)
在 WPF 应用程序中,可以使用 Dispatcher 对象将操作调度到 UI 线程。
示例代码:
using System;
using System.Reflection.Metadata;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using static System.Net.Mime.MediaTypeNames;class MainWindow : Window
{private Button button;private TextBlock textBlock;public MainWindow(){button = new Button { Content = "Start Thread" };textBlock = new TextBlock { Text = "Waiting..." };button.Click += Button_Click;var stackPanel = new StackPanel();stackPanel.Children.Add(button);stackPanel.Children.Add(textBlock);Content = stackPanel;}private void Button_Click(object sender, RoutedEventArgs e){Thread thread = new Thread(UpdateTextBlock);thread.Start();}private void UpdateTextBlock(){for (int i = 0; i < 10; i++){// 使用 Dispatcher 将操作调度到 UI 线程textBlock.Dispatcher.Invoke(() => textBlock.Text = $"Count: {i}");Thread.Sleep(500); // 模拟工作}}
}class Program
{[STAThread]static void Main(){var app = new Application();app.Run(new MainWindow());}
}
解释:
- Dispatcher.Invoke:同步执行指定的操作,确保操作在 UI 线程上运行。
- Dispatcher.BeginInvoke:异步执行指定的操作,不阻塞当前线程。
输出效果:
点击按钮后,TextBlock 的文本会每 500 毫秒更新一次,显示当前计数值。
3. 使用 SynchronizationContext
SynchronizationContext 是一种更通用的方式,适用于 Windows Forms 和 WPF,甚至其他框架(如 ASP.NET)。它允许你捕获当前线程的上下文,并在需要时将其用于调度操作。
示例代码:
using System;
using System.Reflection.Emit;
using System.Threading;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;class Program : Form
{private Button button;private Label label;private SynchronizationContext _uiContext;public Program(){button = new Button { Text = "Start Thread", Dock = DockStyle.Top };label = new Label { Text = "Waiting...", Dock = DockStyle.Fill };button.Click += Button_Click;Controls.Add(label);Controls.Add(button);// 捕获 UI 线程的上下文_uiContext = SynchronizationContext.Current;}private void Button_Click(object sender, EventArgs e){Thread thread = new Thread(UpdateLabel);thread.Start();}private void UpdateLabel(){for (int i = 0; i < 10; i++){// 使用 SynchronizationContext 将操作调度到 UI 线程_uiContext.Post(_ => label.Text = $"Count: {i}", null);Thread.Sleep(500); // 模拟工作}}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new Program());}
}
解释:
- SynchronizationContext.Current:捕获当前线程的上下文(通常是 UI 线程的上下文)。
- Post:异步执行指定的操作。
- Send:同步执行指定的操作。
输出效果:
点击按钮后,label 的文本会每 500 毫秒更新一次,显示当前计数值。
相关文章:
聊透多线程编程-线程基础-3.C# Thread 如何从非UI线程直接更新UI元素
目录 1. 使用 Control.Invoke 或 Control.BeginInvoke(Windows Forms) 2. 使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke(WPF) 3. 使用 SynchronizationContext 桌面应用程序(如 Windows Forms 或 WPF…...
VMware Fusion Pro 13 for Mac虚拟机
VMware Fusion Pro 13 for Mac虚拟机 文章目录 VMware Fusion Pro 13 for Mac虚拟机一、介绍二、效果下载 一、介绍 VMware Fusion Pro for Mac,是一款mac虚拟机软件,跟Parallels Desktop一样,都可以让你的 Mac 同时运行一个或多个不同的操作…...
7.第二阶段x64游戏实战-string类
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:7.第二阶段x64游戏实战-分析人物属性 string类是字符串类,在计算机中…...
【debug莫名其妙跑飞了】
现象:就是在初始化汇编里跑飞了,也可能运行起来时钟不对 原因:调试器调试程序时会执行reset复位,reset没有正确执行。 细节决定成败,事出反常必有妖,忽略的小卡拉米最后能玩死你啊...
【Git 常用操作指令指南】
一、初始化与配置 1. 设置全局账户信息 git config --global user.name "用户名" # 设置全局用户名 git config --global user.email "邮箱" # 设置全局邮箱 --global 表示全局生效,若需针对单个仓库配置,可省略该参数 2.…...
基础知识补充篇:什么是DAPP前端连接中的provider
专栏:区块链入门到放弃查看目录-CSDN博客文章浏览阅读352次。为了方便查看将本专栏的所有内容列出目录,按照顺序查看即可。后续也会在此规划一下后续内容,因此如果遇到不能点击的,代表还没有更新。声明:文中所出观点大多数源于笔者多年开发经验所总结,如果你想要知道区块…...
openssl源码分析之加密模式(modes)
openssl实现分组加密模式(例如AES128-CBC的CBC部分)的模块名字叫做modes,源代码位于 https://gitee.com/gh_mirrors/openssl/tree/master/crypto/modes 博主又打不开github了TT,只能找个gitee镜像 头文件是modes.h。 该模块目前…...
【PVR】《Palm Vein Recognition and Large-scale Research based on Deep Learning》
邬晓毅. 基于深度学习的掌静脉识别及规模化研究[D]. 四川:电子科技大学,2024. 文章目录 1、背景2、相关工作3、创新点和贡献4、方法和实验4.1、知识介绍4.2、基于自适应损失函数的掌静脉识别算法研究4.3、退化图像的掌静脉识别鲁棒性提升研究4.4、掌静脉识别系统规模化 5、总结…...
ES6规范新特性总结
ES6新特性 var、let和const不存在变量提升暂时性死区不允许重复声明 解构赋值用途:交换变量的值从函数返回多个值提取JSON数据遍历map结构输入模块的制定方法 字符串的扩展codePointAt()String.fromCharCode()at()includes(),startsWith(),endsWith()repeat()padSta…...
PyQt学习记录
PyQt学习记录 要在界面上 创建一个控件,就需要在程序代码中 创建 这个 控件对应类 地一个 实例对象。 在Qt系统中,控件(widget)是 层层嵌套 的,除了最顶层的控件,其他的控件都有父控件。 几个函数 函数mo…...
嵌入式硬件篇---Uart和Zigbee
文章目录 前言一、UART(通用异步收发传输器)1. 基本概念2. 工作原理帧结构起始位数据位校验位停止位 异步通信波特率 3. 特点优点缺点 4. 典型应用 二、ZigBee1. 基本概念2. 技术细节工作频段2.4GHz868MHz 网络拓扑星型网络网状网络簇状网络 协议栈物理层…...
代码随想录算法训练营--打卡day8
一.反转字符串II 1.题目链接 541. 反转字符串 II - 力扣(LeetCode) 2.思路 循环分组定位:使用 for 循环,每2k为一组。i 每次增加 2k ,就相当于定位到下一组字符的起始位置。在每次循环中,确定当前组需要…...
Linux 学习笔记(5)路径知识详解:绝对路径、相对路径与特殊路径符(期末、期中复习必备)
前言 一、相对路径与绝对路径 1、概念阐述 2、实际示例 二、特殊路径符 1.特殊路径符介绍 2.应用场景 三、总结 四、结语 前言 在 Linux 系统的学习过程中,路径的概念至关重要,它是我们在文件系统中定位文件和目录的关键。今天,我们就…...
Trae + LangGPT 生成结构化 Prompt
Trae LangGPT 生成结构化 Prompt 0. 引言1. 安装 Trae2. 克隆 LangGPT3. Trae 和 LangGPT 联动4. 集成到 Dify 中 0. 引言 Github 上 LangGPT 这个项目,主要向我们介绍了写结构化Prompt的一些方法和示例,我们怎么直接使用这个项目,辅助我们…...
【ida】ida笔记
1 ida下载 IDA Pro 7.0 Windows 和 macOS 版本,包含全部 F5 插件 - 资源分享 - iOS 安全论坛 - 专注于研究 iOS 安全 - iOS Hacker 2 IDA基操 1 shiftF12 查看string信息 (通常可以看到重要的信息 ) 2 Alt T 查找带有目标字符串的函数 3 F5 查看C代码 4 Ctrl F…...
动态规划——两个数组的dp问题
目录 1. 最长公共子序列 2. 不相交的线 3. 不同的子序列 4. 通配符匹配 5. 正则表达式匹配 6. 交错字符串 7. 两个字符串的最小ASCII删除和 8. 最长重复子数组 1. 最长公共子序列 题目链接:1143. 最长公共子序列 - 力扣(LeetCode࿰…...
stream流Collectors.toMap(),key值重复问题
文章目录 一、问题二、问题示例三、原因四、解决方法4.1、方案一 一、问题 发现Collectors.toMap的一个坑,若key值重复的时候会抛异常。如: IllegalStateException: Duplicate key 男 二、问题示例 报错示例如下: import lombok.AllArgsC…...
机器学习 Day10 逻辑回归
1.简介 流程就是: 就是我们希望回归后激活函数给出的概率越是1和0. 2.API介绍 sklearn.linear_model.LogisticRegression 是 scikit-learn 库中用于实现逻辑回归算法的类,主要用于二分类或多分类问题。以下是对其重要参数的详细介绍: 2.1.…...
即时通讯软件BeeWorks,企业如何实现细粒度的权限控制?
BeeWorks作为一款专为企业设计的即时通讯平台,高度重视用户隐私安全,采取了多种措施来保障数据的保密性、完整性和可用性。 首先,BeeWorks采用私有化部署模式,企业可以将服务器架设在自己的网络环境中,所有通讯数据&a…...
Seq2Seq - Dataset 类
本节代码定义了一个 CMN 类,它继承自 PyTorch 的 Dataset 类,用于处理英文和中文的平行语料库。这个类的主要作用是将文本数据转换为模型可以处理的格式,并进行必要的填充操作,以确保所有序列的长度一致。 ⭐重写Dataset类是模型训…...
学习OpenCV C++版
OpenCV C 1 数据载入、显示与保存1.1 概念1.2 Mat 类构造与赋值1.3 Mat 类的赋值1.4 Mat 类支持的运算1.5 图像的读取与显示1.6 视频加载与摄像头调用1.7 数据保存 参考:《OpenCV4快速入门》作者冯 振 郭延宁 吕跃勇 1 数据载入、显示与保存 1.1 概念 Mat 类 : Ma…...
echarts图表相关
echarts图表相关 echarts官网折线图实际开发场景一: echarts官网 echarts官网 折线图 实际开发场景一: 只有一条折线,一半实线,一半虚线。 option {tooltip: {trigger: "axis",formatter: (params: any) > {const …...
idea自动部署jar包到服务器Alibaba Cloud Toolkit
安装插件:Alibaba Cloud Toolkit 配置服务器: 服务器配置: 项目启动Shell脚本命令: projectpd-otb.jar echo 根据项目名称查询对应的pid pid$(pgrep -f $project); echo $pid echo 杀掉对应的进程,如果pid不存在,则不执行 if [ …...
奥利司他
https://m.baidu.com/bh/m/detail/ar_9900965142893895938 奥利司他(四氢脂抑素)是一种众所周知的胰腺和胃脂肪酶不可逆抑制剂 生物活性:奥利司他(四氢脂抑素)是一种众所周知的胰腺和胃脂肪酶不可逆抑制剂。奥利司…...
Element Plus 图标使用方式整理
Element Plus 图标使用方式整理 以下是 Element Plus 图标的所有使用方式,包含完整代码示例和总结表格: 1. 按需引入图标组件 适用场景:仅需少量图标时,按需导入减少打包体积 示例代码: <template><div>…...
链路聚合+vrrp
1.链路聚合 作用注意事项将多个物理接口(线路)逻辑上绑定在一起形成一条逻辑链路,起到叠加带宽的作用1.聚合接口必须转发速率一致。2.聚合设备两端必须一致 配置命令 方法一 [Huawei]interface Eth-Trunk 0----先创建聚合接口,…...
Dynamics 365 Business Central Register Customer Payment 客户付款登记
#Dynamics 365 BC ERP# #D365 ERP# #Navision 前言 在实施过程,经常给客户介绍的 给客户付款一般用Payment Journal. 在客户熟悉系统运行后,往往会推荐客户使用Register Customer Payment.用这个function 工作会快很多,但出错的机会也比较大…...
Odoo免费开源ERP:企业销售过程中出现的问题
在企业未上线Odoo免费开源ERP时,企业销售过程中会存在失误。比如,许多销售订单都有如下问题:不当的定价、向客户过多地询问、处理订单延误、错过发货日期等。这些问题源于企业三个未集成的信息系统:销售管理系统、库存系统和财务系…...
手撕unique_ptr 和 shareed_ptr
文章目录 unique_ptrshared_ptr unique_ptr template<class T> class Unique_ptr { private:T* ptrNULL; public://1、删除默认的拷贝构造函数Unique_ptr(Unique_ptr& u) delete;//2、删除默认的复制构造Unique_ptr& operator(Unique_ptr& u) delete; …...
工会考试的重点内容是什么
工会考试的内容通常涵盖以下几个方面: 1、政治理论: 主要考查考生对马克思主义基本原理、中国特色社会主义理论体系、党的基本路线、方针、政策等方面的掌握程度。题型通常包括选择题、判断题和论述题。 2、法律法规: 这部分主要涉及国家…...
