WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C

2023-05-16

WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用


Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 Control 线程安全。

在跨线程更新的时候,Control 会检查 CurrentThread 是否为创建 Control 的线程,并报错!

示例代码如下: 

示例代码
private   void  btnStart_Click( object  sender, EventArgs e)
{
     
// 注意:特地不使用 Timer 控件
     Thread thread  =   new  Thread(Fun);
     thread.Start(DateTime.Now.ToString());
}

// 报错:线程间操作无效: 从不是创建控件“lblTime”的线程访问它。
private   void  Fun( object  datetime)
{
     lblTime.Text 
=  ( string )datetime;
}


最简单的解决方式是在程序代码中添加如下属性:

        Control.CheckForIllegalCrossThreadCalls = false;


在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。

将要做的事情放在工作线程中执行,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的。

 

使用 BeginInvoke 方法解决该问题的代码如下:

使用BeginInvoke方法
using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Text;
using  System.Windows.Forms;
using  System.Threading;

namespace  Invoke_Test
{
    
public   partial   class  Form1 : Form
    {

        
// private System.Windows.Forms.Label lblTime;
        
// private System.Windows.Forms.Button btnStart;

        
public  Form1()
        {
            InitializeComponent();
            
//  解决方式一
            
//  Control.CheckForIllegalCrossThreadCalls = false;
        }

        
private   void  btnStart_Click( object  sender, EventArgs e)
        {
            
string  arg  =  DateTime.Now.ToString();

            
//  注意:创建子线程间接调用
            Thread thread  =   new  Thread(FunStart);
            thread.Start(arg); 
// arg 给方法传参  
        }

        
//  定义调用方法的委托
         delegate   string  FunDelegate( string  str);

        
//  注意:特地使用 FunStart 方法模拟间接调用
         private   void  FunStart( object  obj)
        {
            
//  要调用的方法的委托
            FunDelegate funDelegate  =   new  FunDelegate(Fun);

            
/* ========================================================
             * 使用this.BeginInvoke方法
             * (也可以使用this.Invoke()方法)
            ========================================================
*/

            
//  this.BeginInvoke(被调用的方法的委托,要传递的参数[Object数组])
            IAsyncResult aResult  =   this .BeginInvoke(funDelegate,obj.ToString());

            
//  用于等待异步操作完成(-1表示无限期等待)
            aResult.AsyncWaitHandle.WaitOne( - 1 );

            
//  使用this.EndInvoke方法获得返回值
             string  str  =  ( string ) this .EndInvoke(aResult);
            MessageBox.Show(str.ToString());
        }

        
//  真正需要执行的方法
         private   string  Fun( string  datetime)
        {
            lblTime.Text 
=  ( string )datetime;
            
return   " 委托的返回值 " ;
        }
    }
}


Control.InvokeRequired 属性:当前线程不是创建控件的线程时为 true。
也可以认为,在 new Control() 的时候,Control 用一个变量记录下了当前线程,在调用 InvokeRequired 时,返回当前线程是否不等于 new 的时候记录下来的那个线程。

 

Control.Invoke 和 Control.BeginInvoke 就是“发短信”的方法,如果使用 Control.Invoke 发短信,那么甲线程就会像个痴情的汉子,一直等待着乙线程的回音,而如果使用 Control.BeginInvoke 发送短信,那发完短信后,甲线程就会忙活自己的,等乙线程处理完再来瞧瞧。


推荐阅读:WinForm二三事(三)Control.Invoke&Control.BeginInvoke 

示例代码Invoke_Test 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C 的相关文章

  • 如何终止一个无限循环线程和 程序退出时销毁线程

    http zhidao baidu com question 299079849 html android 启动了一个子线程 这个子线程是一个死循环 不成的打印 Hello 现在要实现点击一个Button 让这个子线程终止 用什么方法啊 s
  • 一、使用interrupt()中断线程

    当一个线程运行时 另一个线程可以调用对应的Thread对象的interrupt 方法来中断它 该方法只是在目标线程中设置一个标志 表示它已经被中断 并立即返回 这里需要注意的是 如果只是单纯的调用interrupt 方法 线程并没有实际被中
  • thread_Timer(线程中定时器)

    package com gzhs zsd thread import java util Date import java util Timer import java util TimerTask Timer定时器运用 author 谢泽
  • visual studio2019(C#/.NET)安装教程

    前言 好久没有跟新版本了 博主还用的2017 看到最新的2019功能还是很强大的 版本可能越高越好 所以博主写了一个详细的博客 希望可以帮助到大家 一 visual studio 2019 下载 1 下载地址 visual studio官方
  • 我在 Windows 窗体中的跨线程调用出了什么问题?

    我在使用 Windows 窗体应用程序时遇到问题 表单必须从另一个线程显示 所以在表单类中 我有以下代码 private delegate void DisplayDialogCallback public void DisplayDial
  • 帮助在调用新操作时理解 C# 语法

    我是 C 新手 不了解调用新操作的语法 甚至不了解操作是什么 根据我对 Port1 DataReceived 的理解 我必须创建一个操作 因为我处于新的阶段 任何人都可以详细说明为什么我需要这样做吗 public Form1 Initial
  • 扩展 Control 以提供一致安全的 Invoke/BeginInvoke 功能是否合适?

    在我维护一个严重违反 winforms 中跨线程更新规则的旧应用程序的过程中 我创建了以下扩展方法 作为在发现非法调用时快速修复它们的方法
  • 以编程方式调用按钮的单击方法

    简单的问题 我认为 我希望能够在预定义的对象上调用单击方法 特别是bindingNavigatorDeleteItem标准 c 上的按钮BindingNavigator 我需要拦截删除 以便我可以验证该记录是否允许被删除 如果是 我想调用前
  • 在Java中动态加载类并调用方法

    假设我想在java中动态加载一个类并调用它start 没有参数 方法 Class
  • C# Winforms 线程:调用封闭表单

    下面的代码演示了我的困境 该代码创建一个后台线程来处理某些内容 然后使用结果调用 UI 线程 如果后台线程在窗体关闭后调用窗体上的 Invoke 则可能会引发异常 它在调用 Invoke 之前检查 IsHandleCreated 但表单可能
  • WPF Dispatcher.调用“挂起”

    我有一个有点复杂的 WPF 应用程序 当尝试使用调度程序在 UI 线程上调用调用时 该应用程序似乎 挂起 或陷入 Wait 调用中 一般流程是 处理按钮上的点击事件 创建一个新线程 STA 创建演示者和 UI 的新实例 然后调用该方法断开
  • 避免在释放控件时调用 Invoke

    我的工作线程中有以下代码 ImageListView下面是源自Control if mImageListView null mImageListView IsHandleCreated mImageListView IsDisposed i
  • PowerShell Invoke-Sqlcmd 切换到 sqlps 会话

    我正在 PowerShell ISE 中编写脚本 并使用 Invoke Sqlcmd 执行命令后 Powershell 会话切换到 sqlps 会话 PS SQLSERVER gt 我无法第二次执行脚本 我必须退出 PowerShell I
  • 反射:如何使用参数调用方法

    我试图通过带有参数的反射来调用方法 我得到 对象与目标类型不匹配 如果我调用一个不带参数的方法 它工作得很好 如果我调用该方法 则基于以下代码Test TestNoParameters 效果很好 但是如果我打电话Test Run 我得到一个
  • wpf:通过调度程序更新多个控件

    我正在使用 SerialPort 类中的事件侦听器从串行端口读取数据 在我的事件处理程序中 我需要使用通过串行端口传入的 xml 数据来更新窗口中的许多 30 40 控件 我知道我必须使用 myControl Dispatcher Invo
  • Winforms 到 WPF 的转换:BeginInvoke 到什么?

    这是我在 WinForms 中的旧代码 private void ValueChanged double inValue1 double inValue2 only manual mode for this driver so that s
  • GUI什么时候会过载?

    假设你是永久在 UI 线程 调度程序上异步调用方法 while true uiDispatcher BeginInvoke new Action
  • 跨线程操作无效:从创建它的线程以外的线程访问控制“textBox1”[重复]

    这个问题在这里已经有答案了 我想使用 UART 将温度值从微控制器发送到 C 接口并显示温度Label Content 这是我的微控制器代码 while 1 key scan get value of temp if Usart Data
  • 从 C# 调用 PowerShell cmdlet 会抛出 CommandNotFoundException

    我正在尝试致电Add AppxPackage来自 C 的 cmdlet 我找到了 MSDN 文章从 C 代码运行 PowerShell http msdn microsoft com en us library dd182449 28v v
  • Control.BeginInvoke 是否有一个变体可以在句柄被销毁之前/之后工作?

    我有一个显示底层异步对象状态的控件 该对象引发事件 这些事件到达表单 在那里它们基本上排队并最终使用 BeginInvoke 进行调用 当控件被废弃时就会出现问题 因为事情是异步发生的 这意味着事件回调在处理过程中总是可能排队 所以我有时会

随机推荐

  • 双缓冲技术绘图原理及简单的VC实现

    为了增加自己对双缓冲绘图技术的理解 xff0c 简要做个笔记 xff08 以Windows为例 xff09 xff1a 1 Windows 绘图原理 我们在 Windows 环境下看到各种元素 xff0c 如菜单 按钮 窗口 图像 xff0
  • C#中Tuple的使用

    定义 xff1a 元组是具有 特定数量和序列 的元素 的数据结构 xff08 注意断句哈 xff01 xff09 元组通常有四种使用方式 一 表示一组数据 例如 xff0c 一个元组可以表示一条数据库记录 xff0c 并且每一个分量对应表示
  • 调用C++dll

    1 dll 的优点 代码复用是提高软件开发效率的重要途径 一般而言 xff0c 只要某部分代码具有通用性 xff0c 就可将它构造成相对独立的功能模块并在之后的项目中重复使用 比较常见的例子是各种应用程序框架 xff0c ATL MFC 等
  • DLL程序入口DllMain详解

    DLL程序入口点函数 xff1a DllMain xff0c 注意 xff1a 大小写是区别的 仅导出资源的DLL可以没有DllMain函数 函数原型 cpp view plain copy print BOOL APIENTRY DllM
  • C++编写DLL的方法

    在写C 43 43 程序时 xff0c 时常需要将一个class写成DLL xff0c 供客户端程序调用 这样的DLL可以导出整个class 也可以导出这个class的某个方法 一 导出整个class 方法很简单 xff0c 只需要在类的头
  • dll文件的c++制作

    1 首先用vs2005建立一个 c 43 43 的dll 动态 链接 库 文件 xff0c 这时 xff0c DllTest cpp 定义 DLL 应用程序的入口点 include 34 stdafx h 34 include 34 Dll
  • vs2008 C++创建和调用标准DLL

    为了共享代码 xff0c 需要生成标准的dll xff0c 本文将介绍在vs2008 C 43 43 生成及调用dll 一 生成DLL 生成一个名为FunDll的dll文件 xff0c 对外函数为addl step1 vs2008 环境下
  • VSCode使用SSH免密登录服务器

    VSCode使用SSH免密登录服务器 前言一 SSH连接服务器1 1 安装ssh插件1 2 配置连接 二 免密登录服务器2 1 生成公钥2 2 服务器新建授权文件2 3 本地复制公钥到服务器 总结 前言 vscode使用remote ssh
  • 使用directX 7结合C#进行2D游戏编程

    使用directX 7结合C xff03 进行2D游戏编程 前言 对于C 的开发人员来讲 xff0c GDI 43 是一个拥有丰富的绘图API指令 传统 高效的程序集 但不幸的是 xff0c 你要想用她来开发一个复杂而又平滑的动画的时候 x
  • DirectX学习笔记_关于Sprite.Draw2D的说明

    在DirectX的Sprite中提供一个Draw2D的方法 xff0c 该方法绘制一个 Sprite 对象用于二维空间中显示 xff0c 在DirectX 9 0C中 xff0c 该方法有6个重载 xff0c 分别是 1 public vo
  • 关于Direct2D

    关于Direct2D Direct2D是一个硬件加速的 xff0c 提供立即模式的二维图形API 它提供了二维的几何体 xff0c 位图 xff0c 文本的高性能 xff0c 高质量的渲染 十分方便的是 xff0c Direct2D与GDI
  • C# GDI+ 绘图

    1 坐标系统 1 坐标原点 xff1a 在窗体或控件的左上角 xff0c 坐标为 0 0 2 正方向 xff1a X轴正方向为水平向右 xff0c Y轴正方向为竖直向下 3 单位 xff1a 在设置时 xff0c 一般以像素为单位 xff0
  • lock锁和monitor.enter锁

    210 08 05 14 50 28 转载 Lock object 锁的使用 using System using System Threading namespace program class wangjun public static
  • windows重绘机制原理

    一 Windows程序中的绘制和更新 与DOS环境比较 xff0c Windows中的应用程序在处理文字和图形绘制时有以下区别 xff1a 1 只能在窗口的客户区域绘制文字和图形 2 在窗口上绘制的内容不一定能够保留到程序下一次有意地改写时
  • C# Winform 出现异常:无法将顶级控件添加到控件,解决方案如下:

    Form1Test frm 61 new Form1Test frm TopLevel 61 false 重要的一个步骤 frm Parent 61 splitContainerPanel Panel2 frm Show
  • c#中的Form.Show和Form.ShowDialog的区别

    出处 xff1a http hi baidu com cysteine blog item 01e32224702ff5398744f9bf html 区别1 xff1a ShowDialog是模态的 xff08 独占用户输入 xff09
  • 浅析C#中foreach引用变量

    昨天做老师的网站作业 要对一些对象做添加修改删除处理 别的倒没什么 xff0c 删除时出现了点问题似的 因为是从一个类的集合中删除掉一个元素 这样就要遍历整个集合 xff0c 而foreach正是为遍历准备的新玩意 自然而然用上了 于是代码
  • 用汇编的眼光看C++(之拷贝、赋值函数)

    拷贝构造函数和复制函数是类里面比较重要的两个函数 两者有什么区别呢 xff1f 其实也很简单 xff0c 我们可以举个例子 xff0c 加入有这样一个类的定义 xff1a cpp view plain copy class apple pu
  • IDEA配置一个入门的ssh事例,解决Artifact war exploded:Error during artifact deployment. See server log for detail

    首先 xff0c 我的版本ideaIU 2017 3 4 xff0c 一 新建一个项目project 1 1 create new project 2 file new project 2 这里选择spring xff0c struts2
  • WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C

    WinForm 之Control Invoke 和Control BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用 但可以通过 invoke 来保证 Control 线程安全 在跨线程更新的时候