日期:2014-06-10  浏览次数:20540 次

Control.InvokeRequired 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。

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处理。

实例如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WinThreadNew
{
    public partial class WinThreadNew : Form
    {
        int pro = 0;
        Thread backWork = null;  //后台线程
        public WinThreadNew()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            backWork = new Thread(new ThreadStart(doWork)); //创建新的线程
            backWork.Start();   //启动线程
        }

        public delegate void DelegateUpdateUIPro();
        private void doWork()
        {
            for (int i = 0; i < 100; i++ )
            {
                pro++;
                UpdateUIPro();  //在新线程中更新ui
                Thread.Sleep(100);
            }
            
        }

        private void UpdateUIPro()
        {
           //更新ui时需要判断InvokeRequired 属性
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new DelegateUpdateUIPro(UpdateUIPro));
            } 
            else
            {
                this.lblPro.Text = pro.ToString() + "%";
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.backWork.Abort();
            this.backWork.Join();
        }
    }
}