from:http://www.th7.cn/Program/net/201306/140033.shtml

Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。

如果已经创建控件的句柄,则除了 InvokeRequired 属性以外,控件上还有四个可以从任何线程上安全调 用的方法,它们是: Invoke、 BeginInvoke、 EndInvoke 和 CreateGraphics。 在后台线程上创建控件的句柄之前调用 CreateGraphics 可能会导致非法的跨线程调用。 对于所有其他方法调用,当从另一个线程进行调用时,应使用这些 Invoke 方法之一。

如果控件句柄尚不存在,则 InvokeRequired 沿控件的父级链搜索,直到它找到有窗口句柄的控件或窗体为止。 如果找不到合适的句柄, InvokeRequired 方法将返回 false。

这意味着如果不需要 Invoke(调用发生在同一线程上),或者如果控件是在另一个线程上创建的但尚未创建控件的句柄,则 InvokeRequired 可以返回 false。

如果尚未创建控件的句柄,您就不能简单地在控件上调用属性、方法或事件。这可能导致在后台线程上创建控件的句柄,从而隔离不带消息泵的线程上的控件并使应用程序不稳定。

当 InvokeRequired 在后台线程上返回 false 时,您也可以通过检查 IsHandleCreated 的值来避免这种情况。 如果尚未创建控件句柄,您必须等到控件句柄已创建,才能调用 Invoke 或 BeginInvoke。 通常,仅当在应用程序主窗体的构造函数中创建了后台线程时(如同在 Application.Run(new MainForm()) 中),在已经显示窗体或取消 Application.Run 之前,才会发生这种情况。

一种解决方案是等到已经创建了窗体的句柄,然后启动后台线程。通过调用 Handle 属性强制创建句柄,或者等待 Load 事件启动后台进程。

一种更好的解决方案是使用 SynchronizationContext 返回的 SynchronizationContext,而不是使用控件进行线程间封送处理。——MSDN

关于这方面一个更容易的解释以及例子(参考链接:关于invokeRequired与invoke):

而关于InvokeRequired与Invoke是个老生常谈的问题,一般标准写法为(图片截图来自:Avoiding InvokeRequired,下同):

这种方式的好处就是能在.NET 1.0+上正常运行,但是如果存在很多控件的话,就会存在这样很多代码(大量定义委托)。

而在.NET 2.0上,可以采用匿名委托和MethodInvoker,简化代码写法,关于MethodInvokerMSDN上的定义如下:

MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。 在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。

或者更简洁的写法:

而在.NET 3.5+可以利用其特性,代码如下(截图来在:A Generic Method for Cross-thread Winforms Access

参考资料:

关于invokeRequired与invoke

Avoiding InvokeRequired

A Generic Method for Cross-thread Winforms Access

关于InvokeRequired与Invoke的更多相关文章

  1. InvokeRequired和Invoke

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

  2. 线程——委托InvokeRequired和Invoke

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

  3. InvokeRequired和Invoke(转)

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

  4. Avoiding InvokeRequired

    Just read a good article to do cross-thread calling in an easy and elegant way. It is amazing for it ...

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

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

  6. [C#] Control.Invoke方法和跨线程访问控件

    在设计界面时,我们经常需要将一些需要时间才能完成的操作放在另一个线程(不同于UI主线程)中执行.但是这些操作可能需要将其结果或完成情况通知主线程,比如调用窗体的方法,或者触发事件(由界面响应事件),很 ...

  7. Invoke BeginInvoke

    http://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke http://www.codeproject.com/Arti ...

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

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

  9. Winform Timer用法,Invoke在Timer的事件中更新控件状态

    System.Timers.Timer可以定时执行方法,在指定的时间间隔之后执行事件. form窗体上放一个菜单,用于开始或者结束定时器Timer. 一个文本框,显示定时执行方法. public pa ...

随机推荐

  1. LeetCode——Single Number II(找出数组中只出现一次的数2)

    问题: Given an array of integers, every element appears three times except for one. Find that single o ...

  2. Python 元组

    #不可变序列-----元组 tuple #元组和列表十分相似,元组和字符串一样都是不可变的. #元组由不同的元素组成,每个元素可以存储不同类型的数据,例如 #字符串.数字和元组 #元组通常代表一行数据 ...

  3. 【前端开发】优化代码之减少引入,css预编译语言的优点,stylus的使用

    前言:我必须得承认在最最最开始的时候,我对于css的预编译是非常不以为然的,这是错误的.一般在页面编写过程中,我会将需要reset的css放在reset.css中,讲会需要重复用到的放置到public ...

  4. 2015年ACM长春网络赛(准备做掉7道:已经更新到6道)

    总结汇总:模板 int getmax_min(char s[]) {//字符串的最大表示法:返回最小数组下标 , j = , k = ; while(i < len && j & ...

  5. eclipse快捷键积累(持续更新)

    大小写转换:Ctrl+Shift+X;Ctrl+Shift+Y; 打开资源:Ctrl+Shift+R; 打开类型:Ctrl+Shift+T; 调试时查看对象.变量:Ctrl+Shift+I; 打开函数 ...

  6. HDU 3032 Nim or not Nim?(sg函数)

    题目链接 暴力出来,竟然眼花了以为sg(i) = i啊....看表要认真啊!!! #include <cstdio> #include <cstring> #include & ...

  7. 基础知识:Q&A

    1.点乘几何意义? >0,a,b同向,=1时,方向完全相同 =0,垂直 <0,反向,=-1时,方向完全相反 2.叉乘几何意义?叉乘得到的向量的方向怎么确定? aXb ,可以得到 同时垂直于 ...

  8. Sqlserver查询结果,让某列结果合并一列并且逗号分隔。

            create function [dbo].[mergeName](@Id bigint) returns nvarchar(500)     as     begin     dec ...

  9. JavaScript 三级联动

    附件连接下载地址:http://files.cnblogs.com/files/CaktyRiven/js.zip <!DOCTYPE html> <html lang=" ...

  10. UILabel笔记(待完善)

    UIlabel的换行由 numberOfLines 属性控制,当为0时,则会自动换到适合的行数: 换行的模式由 lineBreakMode 属性控制: public enum NSLineBreakM ...