在设计界面时,我们经常需要将一些需要时间才能完成的操作放在另一个线程(不同于UI主线程)中执行。但是这些操作可能需要将其结果或完成情况通知主线程,比如调用窗体的方法,或者触发事件(由界面响应事件),很多情况下这种通知需要访问控件。
但是如果调用上述方法或者触发事件的线程不是控件的创建进程,Control就不能在创建它的thread之外被访问,此时会引发一个异常,好在可以通过控件的invoke方法来访问它。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的 Invoke 方法来将调用封送到适当的线程。
 
一、 Control.InvokeRequired 属性与 Invoke方法
 
Control.InvokeRequired 属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。MSDN中将其解释为“获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
事实上,Control.InvokeRequired返回的结果就是 CurrentThread != ControlCreatThread 而已,在创建者线程和其它线程中,该值不同。
 
比较好的做法如下:
 
首先定义一个与可能被控件的非创建线程调用的方法或者事件处理函数的签名一样委托,如:
private  delegate  void  DeleUpdateText ( string  text );
 
当然直接使用已有的事件的委托也是可以的。
 
然后就是判断这个属性的值来决定是否要调用Invoke函数:
private  void  UpdateText ( string  text )
{
    if(this.InvokeRequired)
    {
        this.Invoke( new  DeleUpdateText( UpdateText ),  new  object[]{text} );
    }
    else
    {
        MyTextBox.Text   =  text;
    }
}
 
需要说明的:
1. Control.Invoke方法的第二个参数为 object[] 类型,作为指定方法的参数传递的对象数组。如果此方法没有参数,该参数可以是 null,或者使用不含该参数的重载版本。
2. 方法返回值的类型为 Object ,它包含正被调用的委托返回值;如果该委托没有返回值,则为 null。
 
二、BeginInvoke 方法
 
使用 Invoke 方法调用委托,在所委托的方法执行完成前,会阻塞进程,另一个更好的选择是异步调用委托的BeginInvoke方法,这个方法总是不等待委托的执行而立刻放回,特别适合于调用后就不用再管的方法执行。当然,也可以使用其返回的IAsyncResult类型的结果,并和委托的 EndInvoke 方法一起使用,以在该方法调用完毕后检索调用结果。
 
其参数和 Invoke 方法类似:
 
// Created on UI thread, but doesn't run on UI thread
private Label lblStatus;
{
    DoSomethingSlow();
    // Do UI update on UI thread
    object[] pList = { this, System.EventArgs.Empty };
    lblStatus.BeginInvoke( new System.EventHandler(UpdateUI), pList); }
    •••
    // Code to be run back on the UI thread
    // (using System.EventHandler signature, 
    // so we don't need to define a new delegate type here)
    private void UpdateUI(object o, System.EventArgs e)
    {
        // Now OK - this method will be called via Control.Invoke, 
        // so we are allowed to do things to the UI.
        lblStatus.Text = "Finished!";
    }
}
 
关于这个问题,发现了一篇讲解的特别清晰透彻的文章(作者:Ian Griffiths),附上原文和译文的名称和链接。似乎中英文版本的图片和代码都有些问题,在搜索引擎上直接搜索文章名或许可以找到排版更好的版本。
 
Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads
 
通过多线程为基于 .NET 的应用程序实现响应迅速的用户

[C#] Control.Invoke方法和跨线程访问控件的更多相关文章

  1. [C#] Control.Invoke方法和跨线程访问控件(转载)

    转载前,在网上找了好多INVOKE方法的文章,就这个看着还可以,明白了大概,以后再深用的时候再研究 ,废话少说上转载(连转载都说的这么有气势,哈哈)   在设计界面时,我们经常需要将一些需要时间才能完 ...

  2. C# WinFrom 跨线程访问控件

    1.跨线程访问控件委托和类的定义 using System; using System.Windows.Forms; namespace ahwildlife.Utils { /// <summ ...

  3. winform跨线程访问控件

    首先说下,.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性.所以除了控件所在的线程外的线程调用会抛异常 (Cross-thread operation not va ...

  4. c#使用MethodInvoker解决跨线程访问控件

      功能函数测试集锦(77)  C#专区(114)  版权声明:本文为博主原创文章,未经博主允许不得转载. .net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生,有一种方法是禁止编译器对跨线 ...

  5. C# 关于跨线程访问控件问题

    跨线程访问控件问题的原因是:控件都是在主线程中创建的,而系统默认控件的修改权归其创建线程所有.在子线程中如果需要直接修改控件的内容,需要使用委托机制将控件的修改操作交给主线程处理.因此,当没有使用委托 ...

  6. C# 跨线程访问控件(MethodInvoker)

    参考:https://www.cnblogs.com/lvdongjie/p/5428815.html .Net 通常禁止跨线程访问控件,设置Control.CheckForIllegalCrossT ...

  7. c#跨线程访问控件帮助类

    1.背景 对于winform程序来说,当我们点击按钮,需要消耗一定时长才能拿到数据后才能显示在界面上某个控件上的情况,我们通常会专门开一个线程去拿数据,这样不会造成界面处于假死状态 2.常规做法 // ...

  8. c# winform InvokeRequired 解决跨线程访问控件

    C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它. Windows 窗体中 ...

  9. C#之Winform跨线程访问控件

    C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...

随机推荐

  1. Squid 反向代理加速网站

    本实例的域名是 wenjin.cache.ibm.com.cn,通过DNS的轮询 技术,将客户端的请求分发给其中一台 Squid 反向代理服务器处理,如果这台 Squid 缓存了用户的请求资源,则将请 ...

  2. ftp在shell脚本中的使用方法

    1. ftp自动登录批量下载文件. #####从ftp服务器上的/home/data 到 本地的/home/databackup#####!/bin/bashftp -n<<!open 1 ...

  3. <十>面向对象分析之UML核心元素之关系

    关系        --->在UML中关系是非常重要的语义,它抽象出对象之间的联系,让对象构成特定的结构.        一,关联关系(association)

  4. HDU 4630-No Pain No Game(线段树+离线处理)

    题意: 给你n个数的序列a,q个询问,每个询问给l,r,求在下标i在[l,r]的区间任意两个数的最大公约数中的最大值 分析: 有了hdu3333经验,我们从左向右扫序列,如果当前数的约数在前面出现过, ...

  5. HDU5764 After a Sleepless Night 树形乱搞题

    分析(官方题解): 假设根已确定,可以发现新树若合法,需满足以下性质:根节点是n:儿子的值不大于父亲:具有相同值的节点形成一条链,并且链不会发生“分叉”(即有多个最低点).所以对于新树中有出现的值x, ...

  6. IOS UIView(UIButton)通过显示动画移动的时候 响应点击的解决方案

    今天在做一个UIButton显示动画的时候,遇到一个问题,就是在移动的时候 ,需要相应它的点击时间(click) 通过CAKeyframeAnimation 来移动UIButton的layer ,效果 ...

  7. unicode ansi utf-8 unicode_big_endian编码的区别

      随便说说字符集和编码  快下班时,爱问问题的小朋友Nico又问了一个问题:  "sqlserver里面有char和nchar,那个n据说是指unicode的数据,这个是什么意思.&quo ...

  8. Text Kit进阶

    在上一篇文章Text Kit入门中我们主要了解了什么是Text Kit及它的一些架构和基本特性,这篇文章中会涉及关于Text Kit的更多具体应用. Text Kit是建立在Core Text框架上的 ...

  9. PHP:6种GET和POST请求发送方法

    在i94web博客中,我试过了畅言和多说两种社会化评论框,后来还是抛弃了畅言,不安全. 无论是畅言还是多说,我都需要从远程抓取文章的评论数,然后存入本地数据库.对于多说,请求的格式如下: // 获取评 ...

  10. stl+模拟 CCF2016 4 路径解析

    // stl+模拟 CCF2016 4 路径解析 // 一开始题意理解错了.... #include <iostream> #include <string> #include ...