日期:2014-05-18  浏览次数:21911 次

关于C# this.InvokeRequired的问题
请问各位兄弟,我这样子写的一段程序,是用来线程去调用窗体控件,进行复制,可是我这样写,程序会卡死的~~~这是为什么了??还有就是this.Invoke与this.BeginInvoke的怎样区别的?如果用了怎样this.BeginInvoke之后,需要调用this.EndInvoke吗?

C# code

    public delegate void DeleTtt();
    public delegate void DeleTttt();

    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread t1 = new Thread(new ThreadStart(progressBarSample));
            t1.IsBackground = true;
            t1.Start();

            Thread t2 = new Thread(new ThreadStart(lblText));
            t2.IsBackground = true;
            t2.Start();
        }

        private void progressBarSample()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DeleTttt(lblText));
            }
            else
            {
                for (int i = 0; i < this.progressBarSample2.Properties.Maximum; i += 50)
                {
                    this.progressBarSample2.Position += i;
                    Thread.Sleep(1500);
                }
            }
        }

        private void lblText()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DeleTtt(lblText));
            }
            else
            {
                while (true)
                {
                    label2.Text += ".";
                    if (label2.Text.Length >= 4)
                    {
                        label2.Text = String.Empty;
                    }
                    Thread.Sleep(1000);
                }
            }
        }
    }



------解决方案--------------------
Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。

Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

以下为实际应用中碰到的问题,在主线程中启动一个线程,然后在这个线程中启动serviceForm,然而在线程启动后,往serviceForm发送指令,serviceForm.IsHandleCreated老是报serviceForm = null,无法执行指令,采用延时的办法可以解决此问题,但不是高效的办法,后来在serviceForm.Load += new EventHandler(serviceForm_Load);serviceForm_Load事件中添加指令,发送成功。主要原因还是多线程所致。
------解决方案--------------------
(一)Control的Invoke和BeginInvoke

我们要基于以下认识:

(1)Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的。

(2)Control的Invoke和BeginInvoke的参数为delegate,委托的方法是在Control的线程上执行的,也就是我们平时所说的UI线程。

我们以代码(一)来看(Control的Invoke)

private delegate void InvokeDelegate();

private void InvokeMethod(){

//C代码段

}

private void butInvoke_Click(object sender, EventArgs e) {

//A代码段.......

this.Invoke(new InvokeDelegate(InvokeMethod));

//B代码段......

}

你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上

A------>C---------------->B

解释:(1)A在UI线程上执行完后,开始Invoke,Invoke是同步

(2)代码段B并不执行,而是立即在UI线程上执行InvokeMethod方法,即代码段C。

(3)InvokeMethod方法执行完后,代码段C才在UI线程上继续执行。

看看代码(二),Control的BeginInvoke

private delegate void BeginInvokeDelegate();

private void BeginInvokeMethod(){

//C代码段

}

private void butBeginInvoke_Click(object sender, EventArgs e) {

//A代码段.......

this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));

//B代码段......

}

你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上

A----------->B--------------->C慎重,这个只做参考。。。。。,我也不肯定执行顺序,如果有哪位达人知道的话请告知。

解释::(1)A在UI线程上执行完后,开始BeginInvoke,BeginInvoke是异步

(2)InvokeMethod方法,即代码段C不会执行,而是立即在UI线程上执行代码段B。

(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后),InvokeMethod方法,即代码段C