• 使用BeginInvoke或Invoke

    • 作用

      • 在自己创建的非UI线程中,进行UI操作,比如更新UI上控件的状态。
      • Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。
      • 如果已经创建控件的句柄,则除了 InvokeRequired 属性以外,控件上还有四个可以从任何线程上安全调用的方法,它们是: Invoke、BeginInvoke、 EndInvoke 和 CreateGraphics。 在后台线程上创建控件的句柄之前调用 CreateGraphics 可能会导致非法的跨线程调用。 对于所有其他方法调用,当从另一个线程进行调用时,应使用这些 Invoke 方法之一。如果控件句柄尚不存在,则 InvokeRequired 沿控件的父级链搜索,直到它找到有窗口句柄的控件或窗体为止。 如果找不到合适的句柄, InvokeRequired 方法将返回 false。
    • 也可以new一个Thread,在其中再使用BeginInvoke或Invoke
      • 这其实就是在自己创建的非UI线程中,又有一部分逻辑是要修改主UI线程的显示,那么就要用BeginInvoke来实现
      • Thread t = new Thread(() =>
        {
        // business logic this.BeginInvoke(new Action(delegate ()
        {
        // ui logic
        })); // business logic this.BeginInvoke(new Action(delegate ()
        {
        // ui logic
        }));
        });
        t.Start();
    • 每个控件都有new、active、disposed三个状态
    • 调用前的检查
      • 否则可能会导致异常:Invoke or BeginInvoke cannot be called on a control until the window handle has been created. (在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke)
      • 因此需要一些属性用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用
        • InvokeRequired

          • 最好在调用的外层套一个InvokeRequired来判断当前是否必须使用Invoke或者BeginInvoke来做动作,为false时即可以直接做动作
          • 这意味着如果不需要 Invoke(调用发生在同一线程上),或者如果控件是在另一个线程上创建的但尚未创建控件的句柄,则InvokeRequired 可以返回 false。如果尚未创建控件的句柄,您就不能简单地在控件上调用属性、方法或事件。这可能导致在后台线程上创建控件的句柄,从而隔离不带消息泵的线程上的控件并使应用程序不稳定。
        • IsHandleCreated
          • 谨慎起见,还可以使用IsHandleCreated来判断该控件是否已经创建了关联的句柄
          • 当 InvokeRequired 在后台线程上返回 false 时,您也可以通过检查 IsHandleCreated 的值来避免上面这种情况。 如果尚未创建控件句柄,您必须等到控件句柄已创建,才能调用 Invoke 或 BeginInvoke。 通常,仅当在应用程序主窗体的构造函数中创建了后台线程时(如同在 Application.Run(new MainForm()) 中),在已经显示窗体或取消 Application.Run 之前,才会发生这种情况
        • 单从检查的角度来说,事实上IsHandleCreate比InvokeRequired要严格,前者为true时,后者肯定是true???;InvokeRequired为false的原因可能是IsHandleCreate为false或者根本不需要Invoke等。
        • 两者的用途不太一样,一个用于判断有没有必要使用Invoke等,一个用于判断控件是否有句柄,虽然两者存在上述关系,所以最好两个属性都进行判断,先后顺序个人感觉无所谓
        •  if(control.IsDisposed || (!control.IsHandleCreated && !control.FindForm().IsHandleCreated))
          {
          // some exceptional condition:
          // handle in whatever way is appropriate for your app
          return;
          } if(control.InvokeRequired)
          {
          control.Invoke(action);
          }
          else
          {
          action();
          }
    • 参考
      • https://www.cnblogs.com/slyzly/articles/2121436.html
      • https://blog.csdn.net/dyllove98/article/details/9105555

WinForm中的多线程的更多相关文章

  1. WinForm中 事件 委托 多线程的应用

    WinForm中 事件 委托 多线程的应用[以一个下载进度条为例] 第一步:首先我们创建一个winfor的项目 第二步:我们建一个窗体在一个窗体里面 打开一个另外的窗体 另外的窗体有一个按钮 点击后就 ...

  2. C#中使用多线程访问Winform中控件的若干问题

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍. 首先来看传统方法: public partial  ...

  3. (转)c#(wince)中使用多线程访问winform中控件的问题

    我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题.然而我们并不能用传统方法来做这个问题,下面我将详细的介绍. 首先来看传统方法:  public partial ...

  4. winform中如何在多线程中更新UI控件--ListView实时显示执行信息

    1.在winform中,所有对UI的操作,都得回到UI线程(主线程)上来,才不会报错 线程间操作无效: 从不是创建控件的线程访问它. 2.在winform中,允许通过Control.invoke对控件 ...

  5. 在 WinForm 中使用 Direct2D

    在 C# 的 WinForm 应用中,界面的绘制使用的是 GDI+.不过在一些特别的应用中,可能需要用硬件加速来提高绘制的效率.下面就来介绍两种在 WinForm 应用中嵌入 Direct2D 的方法 ...

  6. c# winform编程之多线程ui界面资源修改总结篇【转】

    c# winform编程之多线程ui界面资源修改总结篇 单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello Wor ...

  7. 如何跨线程访问Winform中的UI元素

    如何跨线程访问Winform中的UI元素 假如制作一个Socket聊天应用程序,很可能会用到多线程: 例如为Receive方法开辟单独一个线程,例如为Receive方法开辟单独一个线程(后台运行的线程 ...

  8. 转载:WinForm中播放声音的三种方法

    转载:WinForm中播放声音的三种方法 金刚 winForm 播放声音 本文是转载的文章.原文出处:http://blog.csdn.net/jijunwu/article/details/4753 ...

  9. C# Winform 中如何实现音乐播放和视频播放

    C#  Winform 中如何实现音乐播放和视频播放 namespace WindowsFormsApplication1 { public partial class Form2 : Form { ...

随机推荐

  1. HAProxy安装配置用于TCP的负载均衡

    HaProxy介绍 Haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备.虚拟主机.基于TCP和HTTP应用代理等功能.其配置简单,而且拥有很好的对服务器节点的健康检 ...

  2. Java-Runoob:Java 循环结构

    ylbtech-Java-Runoob:Java 循环结构 - for, while 及 do...while 1.返回顶部 1. Java 循环结构 - for, while 及 do...whil ...

  3. PL/SQL 训练03 --异常

    --程序员在开发的时候,经常天真的认为这个世界是完美的,用户如同自己般聪明,总能按照自己设想的方式--操作系统输入数据.但残酷的事实告诉我们,这是不可能的事情,用户总会跟我们相反的方式操作系统--于是 ...

  4. log4net 使用总结- (2)在ASP.NET MVC 中使用

    log4net在ASP.NET MVC中的配置,还有一种配置方式,即不在web.config中,而是单独新建一个log4net.config 在根目录下   第一.引用log4net.dll   第二 ...

  5. NetBeans+Xdebug调试原理

    使用Xdebug的远程调试,Xdebug作为一个嵌入到PHP的程序,扮演着客户端的角色,而IDE则作为服务器.下面的动态图展示了连接建立的过程. 服务端的IP为10.0.1.2, 使用HTTP协议,端 ...

  6. PHP安装使用Zend Opcache扩展

    简介 Zend OPCache 的前身是Zend Optimizer + (Zend O+),于 2013年3月中旬改名为 Opcache.其通过 opcode 缓存和优化提供更快的 PHP 执行过程 ...

  7. Android 从本地图库或拍照后裁剪图片并设置头像

    在QQ和微信等应用都会有设置头像,一般都是从本地图库选取或相机拍照,然后再截图自己喜欢的部分,然后设置.最后一步把截取好的图片再保存到本地,来保存头像.为了大家使用方便,我把自己完整的代码贴出来,大家 ...

  8. leetcode454

    public class Solution { public int FourSumCount(int[] A, int[] B, int[] C, int[] D) { var dic = new ...

  9. js中slice,splice和split方法的区别

    1.slice(数组) 用法:array.slice(start,end) 解释:该方法是对数组进行部分截取,并返回一个数组副本:参数start是截取的开始数组索引,end参数等于你要取的最后一个字符 ...

  10. html-select

    <html><head> <title>select选择标签</title> <meta charset="UTF-8"> ...