.invokeRequired属性和 invoke()方法

问: f (this.InvokeRequired)
            {
                this.BeginInvoke(new MethodInvoker(LoadGlobalImage));
                return;
            }

是什么意思



答: c#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的

当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它,此时它将会在内部调用new MethodInvoker(LoadGlobalImage)来完成下面的步骤,这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了



another:

在设计中为了让界面与逻辑分离,我的做法是使用事件,界面只要响应事件来处理界面的显示就行了。而事件在逻辑处理中可能由不同的线程引发,这些事件的响应方法在修改界面中的控件内容时便会引发一个异常。

这时就用到了Control.InvokeRequired 属性 与Invoke方法。

MSDN中说:
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。 
如果控件的 Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性 。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。

下面来说下这个的用法(我的一般做法):
首先定义一个委托,与这个事件处理函数的签名一样委托,当然直接使用该事件的委托也是可以的,如:

  private    delegate    void  InvokeCallback(  string  msg);

然后就是判断这个属性的值来决定是否要调用Invoke函数:

  void  m_comm_MessageEvent(  string  msg)
     {
     if (txtMessage.InvokeRequired)
     {
     InvokeCallbackmsgCallback  =   new  InvokeCallback(m_comm_MessageEvent);
     txtMessage.Invoke(msgCallback,  new   object []  { msg } );
    } 

     else 
     {
     txtMessage.Text  =  msg;
    } 

   }

说明:这个函数就是事件处理函数,txtMessage是一个文本框。
这样就做到了窗体中控件的线程安全性。

 

------------------

InvokeRequired 当前线程不是创建控件的线程时为true
比如你可以自己开一个Thread,或使用Timer的事件来访问窗体上的控件的时候,在线程中窗体的这个属性就是True的。

简单的说,如果有两个线程,Thread A和Thread B,并且有一个Control c,是在Thread A里面new的。
那么在Thread A里面运行的任何方法调用c.InvokeRequired都会返回false。
相反,如果在Thread B里面运行的任何方法调用c.InvokeRequired都会返回true。
是否是UI线程与结果无关。(通常Control所在的线程是UI线程,但是可以有例外)

也可以认为,在new Control()的时候,control用一个变量记录下了当前线程,在调用InvokeRequired时,返回当前线程是否不等于new的时候记录下来的那个线程。

--------------------

我理解:如果InvokeRequired==true表示其它线程需要访问控件,那么调用invoke来转给控件owner处理。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
VB.NET 显式创建和运行任务 不返回值的任务由 System.Threading.Tasks.Task 类表示。 返回值的任务由 System.Threading.Tasks.Task<TResult> 类表示,该类从 Task 继承。 任务对象处理基础结构详细信息,并提供可在任务的整个生存期内从调用线程访问的方法属性。 例如,可以随时访问任务的 Status 属性,以确定它是已开始运行、已完成运行、已取消还是引发了异常。 状态由 TaskStatus 枚举表示。 在创建任务时,你赋予它一个用户委托,该委托封装该任务将执行的代码。 该委托可以表示为命名的委托、匿名方法或 lambda 表达式。 lambda 表达式可以包含对命名方法的调用,如下面的示例所示。 请注意,该示例包含对 Task.Wait 方法的调用,以确保任务在控制台模式应用程序结束之前完成执行。 Use the Invoke method The following example demonstrates a pattern for ensuring thread-safe calls to a Windows Forms control. It queries the System.Windows.Forms.Control.InvokeRequired property, which compares the control's creating thread ID to the calling thread ID. If they're different, you should call the Control.Invoke method. The WriteTextSafe enables setting the TextBox control's Text property to a new value. The method queries InvokeRequired. If InvokeRequired returns true, WriteTextSafe recursively calls itself, passing the method as a delegate to the Invoke method. If InvokeRequired returns false, WriteTextSafe sets the TextBox.Text directly. The Button1_Click event handler creates the new thread and runs the WriteTextSafe method.
05-31
C# 中,Invoke 是 Control 类的一个方法,用于在 UI 线程上执行指定的委托。在 Windows 窗体应用程序中,所有的 UI 控件都是在 UI 线程上创建和操作的,因此在多线程程序中,如果需要更新 UI 控件的显示,就需要使用 Invoke 方法将更新操作委托到 UI 线程上执行。 Invoke 方法有多个重载形式,最常用的是以下两种: 1. public object Invoke(Delegate method, params object[] args); 该方法接受一个委托参数 method 和一个可选的参数列表 args,用于在 UI 线程上执行指定的委托。方法返回值取决于委托的返回值,如果委托没有返回值,则返回 null。 2. public TResult Invoke<TResult>(Func<TResult> method); 该方法接受一个 Func 委托参数 method,用于在 UI 线程上执行指定的委托并返回结果。方法返回值为委托的返回值。 例如,以下是一个使用 Invoke 方法更新 Label 控件显示的示例: ``` private void UpdateLabel(string text) { if (lblStatus.InvokeRequired) { // 如果当前线程不是 UI 线程,则将更新操作委托到 UI 线程上执行 lblStatus.Invoke(new Action(() => lblStatus.Text = text)); } else { // 如果当前线程是 UI 线程,则直接更新控件显示 lblStatus.Text = text; } } ``` 在这个示例中,我们首先检查当前线程是否是 UI 线程,如果不是则使用 Invoke 方法将更新操作委托到 UI 线程上执行,否则直接更新 Label 控件的 Text 属性的值。这样可以确保在多线程程序中正确地更新 UI 控件的显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值