三种方法实现C#Winform跨线程调用

C#【委托/事件篇】跨线程访问窗体控件的方法 跨线程访问窗体控件的几种方法 阅读详情

关键字:CheckForIllegalCrossThreadCalls、委托、new Action

适用场景

当我们进行Winform开发时,会出现这样一种情况:我们在代码中开启了一个线程,在线程中我们想要获取到界面上的值,亦或是我们想要在线程中给界面上的控件赋值,此时就会出现如下图所示的错误:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxx”的线程访问它。”
线程中想要给textbox赋值
这时,有三种写法可以实现跨线程的赋值。

方法一:关闭对错误线程调用的捕获

使用代码如下

public Form1()
{
    InitializeComponent();
    //^.^增加此行关闭对错误线程调用的捕获
    Control.CheckForIllegalCrossThreadCalls = false;
}

只要在窗体的构造方法中将捕获关闭即可实现跨线程调用不报错,此行代码的添加位置不仅可以在构造方法中,一般来说,只要添加在跨线程调用的代码之前都能起作用。

方法二:使用委托

  • 为什么要使用委托的方式?

跨线程调用报错的原因是我们在在非 UI 线程中对 UI 控件进行了操作,而在C#中, UI 控件不是线程安全的,只能在创建它们的线程(即 UI 线程)上进行访问和修改。此时,我们可以通过this.Invoke(委托实例)的方式将委托传递给 UI 线程的消息队列,UI 线程会在合适的时机从消息队列中取出该委托并执行。

  • 如何实现?

现在假设有一个应用场景:窗体中有一个label标签(其中的Text值为0),有一个按钮控件。
需要实现:点击按钮控件,按钮控件点击事件中开启一个线程。在线程中循环修改label标签的值,使label标签计数,每秒增加+1。
示例
完整代码如下。

 public partial class Form1 : Form
 {

     int count = 0;
     //第一步:定义委托类
     public delegate void SetTextDelegate(string value);
     //第二步:定义委托方法
     public void SetText(string value)
     {
         label1.Text = value;
     }

     public Form1()
     {
         InitializeComponent();
     }

     private void button1_Click(object sender, EventArgs e)
     {
         Thread th = new Thread(LabelAddFunc);
         th.Start();
     }

     //线程方法
     public void LabelAddFunc()
     {
         while (true) {
             count++;
             //第三步:实例化委托类对象
             SetTextDelegate setText = new SetTextDelegate(SetText);
             //第四步:调用委托实现跨线程修改label的值
             this.Invoke(setText, count.ToString());
             Thread.Sleep(1000);//睡眠1s,每秒label值+1
         }
         
     }
 }

核心重点就是this.Invoke(setText, count.ToString());
其中,Invoke的第一个参数是委托的方法,第二个参数是委托方法的输入参数。

这种方法在使用时要写很多代码,非常不方便,那么,有没有更简便的写法呢?有的,就是下面要介绍的第三种方式。

方法三:new Action

方法三在本质上还是用了委托,因为C#帮我们内置了Action委托和Func委托,其中Action是无参数的,Func是有参数的。那么我们可以使用Action来简化方法二的代码。这就是方法三的实现。

public partial class Form1 : Form
{

    int count = 0;


    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread th = new Thread(LabelAddFunc);
        th.Start();
    }

    //线程方法
    public void LabelAddFunc()
    {
        while (true) {
            count++;
            //====使用C#预定义委托===
            this.Invoke(new Action(() =>
            {
                label1.Text = count.ToString();
            }));
            //========================
            Thread.Sleep(1000);//睡眠1s,每秒label值+1
        }
        
    }
}

综上,这就是三种跨线程调用的解决方法,希望对各位小伙伴有帮助,如果您发现了错漏或有更好的实现,欢迎评论区交流^. ^

C#中跨线程调用的方法一点总结 因此,在C#的Windows Forms和WPF等框架中,跨线程调用UI控件成为了一个重要的课题。如果尝试从另一个线程(非UI线程)直接访问或修改UI控件,将会引发异常或导致不可预测的行为。: 后台线程应该专注于执行耗时任务,并通过某种机制(例如,通过事件、回调或返回值)将结果传递回UI线程,然后由UI线程负责更新UI控件。这两个方法都允许你将一个委托(delegate)排队到UI线程的消息队列中,以便在UI线程上执行。: 将跨线程调用UI控件的逻辑封装在单独的方法中,可以使代码更易于理解和维护。 阅读详情

相关推荐

c#winform控件过多卡顿问题解决方案

最近项目中使用Chat控件,根据接收到的串口数据实时绘制数据曲线,但是在绘制曲线时,绘图区闪烁严重,网上找了很多方法,都不起作用,双缓存也不起作用,最后使用。使用该方法时也不能用双缓存,如果使用双缓存,该方法也不起作用,具体什么原因,还不能理解。//为当前控件/窗体生成截图。

我是菜鸟 7789

C# winform 窗体控件跨线程访问

C# winform 窗体控件跨线程访问 System.InvalidOperationException:“线程间操作无效: 从不是创建控件“textBox1”的线程访问它。” 使用委托应对线程安全问题

ctz6d1p的博客 4665

C#winform进度条弹窗实例

MethodInvoker 是位于System.Windows.Forms下的元数据,表示一个委托,该委托可以执行托管代码中声明为void且不接受任何参数的任何方法。在对控件的 invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。项目中,使用MethodInvoker跨线程UI控件调用,使用了委托实现主窗体与进度条窗体之间的进度传递,使用了多线程进行刷新进度,当然也可以使用BackgroundWorker组件。解决跨线程调用UI控件的问题。本文实例讲解进度条弹窗实现过程。

qq_30725967的博客 2459

解决C#跨线程调用窗体控件的问题

C#跨线程访问控件的解决方法

luobeihai的博客 6863

浅谈C#跨线程调用窗体控件(比如TextBox)引发的线程安全问题

如何:对 Windows 窗体控件进行线程安全调用 访问 Windows 窗体控件本质上不是线程安全的。 如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。 还可能会出现其他与线程相关的 Bug,例如争用情况和死锁。 确保以线程安全方式访问控件非常重要。 在未使用 Invoke 方法的情况下,从不是创建某个控件的线程的其他线程调用该控件是不安全的。 以下非线程安全的调用的示例。 // This event handler creates a thread that calls a // Windows Forms control in an unsafe w

TPL5010硬件看门狗电路

在做一些采集频率很低的产品的时候,会考虑电池供电,比如表、电气表等,为了控制功耗,往往会在设备不需要工作的时候让它进入低功耗模式。为了设备的稳定性,避免死机后无法恢复,必须配置看门狗,一般的看门狗芯片,喂狗间隔时间是几秒钟。这样在喂狗和低功耗之间就产生了一个矛盾,频繁的喂狗就需要频繁的醒过来,这样功耗就很难做到很低。这颗看门狗芯片,特别适合上面的应用。2小时的间隔意味着主控芯片每2小时醒过来喂狗一次即可,而在2.5V供电的情况下,功耗仅仅35nA,几乎可以忽略不计。

zxm8513优快云博客 3308

C#winform之跨线程UI调用

C#中UI调用只能在UI生成的那个线程中才能被安全调用。 所以一般使用委托的方式实现对UI的安全调用。 具体代码: if (this.InvokeRequired) this.Invoke(new MethodInvoker(delegate { DC_V.Text = si.DC_V

fenglifeng1987的专栏 3347

FortiOS路径遍历漏洞CVE-2022-41328实战复现:从环境搭建到漏洞利用全记录

本文深入解析FortiOS路径遍历漏洞CVE-2022-41328,从漏洞背景、影响范围到技术原理进行全面剖析。提供详细的漏洞复现环境搭建步骤和实战利用方法,并给出官方修复方案与临时缓解措施,帮助企业有效防御此类防火墙漏洞风险。

weixin_30485379的博客 523

C#WinForm跨线程访问控件泛型方法

WinForm跨线程访问控件泛型方法 /// <summary> /// 跨线程访问控件泛型方法 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="cont"></p...

qq_22263815的博客 304

Android手机免root玩转Kali NetHunter:Termux保姆级安装指南(附Kex VNC配置)

本文提供了一份详细的Android手机免root安装Kali NetHunter的保姆级指南。通过使用Termux终端模拟器,用户无需解锁Bootloader或获取root权限,即可在普通安卓设备上部署完整的Kali Linux渗透测试环境。教程涵盖了从环境准备、NetHunter核心安装到配置Kex VNC实现图形桌面访问的全过程,并附带了电脑投屏与常见问题解决方案,旨在打造一个便携的移动安全学习与测试平台。

weixin_29208327的博客 297

永磁同步电机矢量控制——从三相静止坐标系到d-q坐标系的数学转换

本文深入解析了永磁同步电机矢量控制的核心——从三相静止坐标系到d-q旋转坐标系的数学转换。通过Clark变换和Park变换,将复杂的三相交流系统解耦为易于控制的直流量,从而实现对电机转矩和磁场的独立、精准控制。文章结合物理图像与工程实践,详细阐述了坐标变换的原理、公式推导及其在磁场定向控制(FOC)中的关键作用。

weixin_29294395的博客 118

C#winform跨窗体更新UI,跨线程更新UI

1. 跨线程界面更新 1.1通过委托更新界面 public delegate void RefreshInterface(int num);//创建委托,含有一个参数num bool MyThreadIsRun = false;//用来控制线程状态 private Thread MyThread = null; //创建线程 private void button1_Click(object sender, EventArgs e) { MyThreadIsRun = !MyThreadIsRun

风,停了 9297

【图像处理】德里奇( Deriche)边缘检测器

Deriche边缘检测,同canny算法齐名,因此,知道canny原理,也有必要知道德里奇的检测原理。本篇专门针对德里奇算法展开讨论。

gongdiwudu的专栏 8683

c#winform跨线程操作控件的一种方法,InvokeRequired

  在winform里面如果有创建新线程的话,在线程里面直接操作控件或修改控件的属性是不允许的,虽然有办法让程序运行时忽略跨线程可能产生的问题,从而解决;但是从科学的角度看,该办法并不可取,所以我就用了InvokeRequired的办法解决跨线程操作问题。   先上代码 if (this.InvokeRequired) { this.Invoke(new MethodInvoker(...

m0_38046697的博客 1394

运维颠覆!一文解锁AI赋能运维实战秘籍,效率飙升!

将AI应用于运维工作是一场极具价值的变革,从故障预测与诊断到自动化任务执行,再到资源管理优化,AI都展现出巨大潜力。尽管在实践过程中会面临数据质量、模型复杂性等挑战,但通过合理的技术选型和解决方案,我们能够充分挖掘AI的优势,实现运维工作的高效、智能转型。持续探索和创新AI在运维领域的应用,将为企业的数字化发展提供坚实保障。在科技飞速发展的当下,运维领域正经历着深刻变革,AI的融入成为提升运维效率与质量的关键。本文将深入实战,带你领略AI如何在运维各环节大显身手,让你的运维工作开启智能高效新模式。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 401

【Bug已解决】[Bug]: ValueError: No user query found in messages QWEN 3.5 27B VLLM 0.16.0 NIGHTLY 解决方案

用 vLLM 0.16.0 nightly 给发聊天请求时,服务端在处理消息时抛ValueError,请求失败。

博客 409

修改value_C#WinForm跨线程修改UI界面

背景在我做WinForm开发的过程中,经常会遇到耗时操作或阻塞操作。他们会引发软件的卡顿甚至假死,严重影响软件的使用。因此,这类耗时或阻塞的操作一般都会使用异步的方式去执行,不影响主线程(UI线程)与用户间的交互。但多个线程竞争读写同一个资源往往会造成意想不到的意外结果,UI界面也是一种资源,所以跨线程修改UI界面往往被加以限制。而在Winform中,跨线程修改UI界面同样是不被允许的。...

weixin_40006265的博客 86

Allegro DXF板框导入及将元器件精准放置到特定位置操作

DXF板框导入 选择File-> import -> DXF 点开DXF file 查找文件 3. 选择需要导入的DXF文件 4. 通常结构文件使用的是米制单位,将单位选择为mm,如果不确定DXF 图纸坐标大小,建议勾选incremental addition,软件根据实际DXF图纸大小自动调整背景坐标尺寸以适应DXF图纸 5.打开Edit/View layers 6. 勾选 select all,选择DXF文件所有层;class 一栏选择BOARD GEOMETRY;subcla

sinat_15677011的博客 1万+

C#之winform跨线程调用异常

一、背景 小伙伴们在做winform开发时,如果在子线程中去设置主线程中UI控件的属性,会出现“跨线程调用异常”。如何解决呢? 二、解决思路 比如我们的winform控件是一个TextBox,名字是tbResult,现在需要在子线程中,修改其Text属性,那么如何实现呢? 使用以下代码即可: this.tbResult.Invoke(new Action(()=>{ this.tbRes...

黑夜の骑士的博客 714

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C#WinForm解决跨线程访问控件属性报错

方式一(在程序初始化构造函数中加一行代码): 1 public Form1() 2 { 3 InitializeComponent(); 4 Control.CheckForIllegalCrossThreadCalls = false; //设置不捕获线程异常 5 } 方式二(推荐...

weixin_30411239的博客 385

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C# 跨线程更新UI控件

现象 “线程间操作无效: 从不是创建控件的线程访问它” 分析 C#Winform编程中,不支持跨线程直接更新UI控件。 解决方案 方案1:设置窗体属性,取消线程安全检查。 缺点:非线程安全,建议不使用 //指定不再捕获对错误线程的调用 Control.CheckForIllegalCrossThreadCalls = false; 方案2:使用上下文SynchronizationContext /// <summary> /// 第一步:UI线程的同步上下文 /// </summary&

horse_2007s的博客 2787

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C#Winform程序跨线程给控件赋值

TLlaile的博客 161

c#winform跨线程访问控件

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33850890的博客 182

C# WinForm跨线程访问控件

.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性,会提示错误“跨线程操作无效“。 提供几种方法解决这个问题 1. 设置CheckForIllegalCrossThreadCalls为False CheckForIllegalCrossThreadCalls为...

chenglongjia7701的博客 641

C#WinForm多线程处理相关文章

vs2005 中的多线程(c#),可带参数C#跨线程操作控件+进度条实战 跨线程调用控件

1087

C#-WinForm跨线程修改UI界面

“System.InvalidOperationException”类型的异常在 System.Windows.Forms.dll 中发生,但未在用户代码中进行处理 其他信息: 线程间操作无效: 从不是创建控件“progressBar1”的线程访问它。

猿长大人 1万+
上一篇: JAVA中使用split获取文件的后缀
下一篇: C# TCP 客户端代码
无畏0070
博客等级 码龄7年 2粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值