C# 跨线程操作控件的线程安全性方法

来源:互联网 发布:mac 日历 软件 编辑:程序博客网 时间:2024/05/16 10:00
 

 

一、             引言

        在C#中,经常用到这样一个场景,Windows Form程序启动一个工作者线程执行一部分工作,这样做是为了避免速度慢的工作如果直接调用会使得主Form停止响应一段时间。既然启动了线程,就避免不了线程之间数据传递的事情,相信你有很多种办法能解决,总之注意同步和互斥操作就好。我想说的是,工作线程处理中可能想操作某个主线程的Windows Form的Control,比如按钮,ListView等等更新工作状态之类,直接控制是不行的,不能够跨线程操作另一个线程创建的Windows Form控件。

 

二、相关知识介绍

       Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的 Invoke 方法来将调用封送到适当的线程。         

        属性Control.InvokeRequired   获取一个值,该值指示调用方在调用控件的方法时是否必须通过控件的Invoke方法来实现。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。

        当从另一个线程调用控件的方法或属性时,只有属性InvokeRequired和方法InvokeBeginInvokeEndInvoke CreateGraphics可以直接调用,控件的其他属性和方法的调用必须通过调用控件的Invoke方法来实现。

控件Invoke方法的两种重载形式

 (1)public Object Invoke (Delegate method)

在拥有此控件的基础窗口句柄的线程上执行指定的委托

返回值为正在被调用的委托的返回值,或者如果委托没有返回值,则为 空引用

 

(2)public Object Invoke (Delegate method, params Object[] args)

在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。

method 一个方法委托,它采用的参数的数量和类型与 args 参数中所包含的相同。

args 作为指定方法的参数传递的对象数组。如果此方法没有参数,该参数可以是 空引用

返回值为正被调用的委托返回值;如果该委托没有返回值,则为 空引用

 

 

三、总结

假设在主线程main_thread中有一个控件C,现在为了工作的需要又开启了一个线程thread1。在线程thread1中需要对主线程main_thread中的控件C进行一些操作(例如修改该控件的属性,调用该控件的方法),为了线程安全性考虑,在线程thread1中不能直接操作主线程main_thread中的控件C。具体方法如下:

(1)       先调用控件C的属性InvokeRequired,判断在线程thread1中是否能直接操作主线程main_thread中的控件C。

(2)       如果不能,就必须使用控件C的Invoke方法来将对控件C的一些操作封送到适当的线程。

 

原创粉丝点击