線程間數據通訊與更新

先看以下代碼:

using System;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace 線程間通訊
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //1.創建Invoke函數,大致如下:
        /// <summary>
        /// Delegate function to be invoked by main thread
        /// </summary>
        private void InvokeFun()
        {
            if (prgBar.Value < 100)
            {
                prgBar.Value = prgBar.Value + 1;
                button1.Text = prgBar.Value.ToString();
            }
            if (prgBar.Value == 100)
            {
                MessageBox.Show("完成", this.Text);
                prgBar.Value = 0;
            }
        }

        //2.子線程入口函數:
        /// <summary>
        /// Thread function interface
        /// </summary>
        private void ThreadFun()
        {
            //Create invoke method by specific function
           MethodInvoker mi = new MethodInvoker( this.InvokeFun );
            for( int i = 0; i < 100; i++ )
            {
               this.BeginInvoke( mi );//讓主線程去訪問自己創建的控件.
                Thread.Sleep( 100 );//在新的線程上執行耗時操作.
            }
        }

        //3. Begin from here
        private void button1_Click(object sender, EventArgs e)
        {          
            Thread thdProcess = new Thread(new ThreadStart(ThreadFun));
            thdProcess.Start();

        }
    }
}

在不做處理的情況下,如果子線程訪問由主線程創建的控件時,系統都會報錯,告訴我們線程間不能直接調用.因爲不同的線程是在不同的內存空間中各自無干擾的並行運行着的.那麼要怎麼做才能讓在子線程中訪問到想要訪問的控件呢?

其實,從上面的例子中可以看出,實現線程間通訊其實並不複雜.thdProcess.Start()以後,開始了一個新的線程,這個線程從入口函數ThreadFun()開始.下面就是問題的關鍵了:

代碼中用到了MethodInvoker 委託,在MSDN中是這樣描述它的:該委託可執行託管代碼中聲明爲 void 且不接受任何參數的任何方法,在對控件的 Invoke 方法進行調用時或需要一個簡單委託又不想自己定義時可以使用該委託。在這裏它實際上就代表了InvokeFun()方法.
另一個重要的方法:BeginInvoke(Delegate) ,它表示在創建控件的基礎句柄所在線程上異步執行指定委託。它可異步調用委託並且此方法立即返回。可以從任何線程(甚至包括擁有該控件句柄的線程)調用此方法。如果控件句柄尚不存在,則此方法沿控件的父級鏈搜索,直到它找到有窗口句柄的控件或窗體爲止。這裏就是通過這個異步調用來完成子線程對主線程上相應控件的訪問的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章