Winform利用多線程、委託、invoke解決界面卡死問題

假設在winform中有如下代碼:

private void button1_Click(object sender, EventArgs e)    
    {       
            int i = 0;
            while (true)
            {
                i = i + 2;
                richTextBox1.AppendText(i.ToString() + "\r\n");
                richTextBox1.ScrollToCaret();

            }
        ...
     }

則程序運行後會出現界面卡死無法響應操作的現象,如何解決?

首先,在窗體內建立一個成員方法來實現上述代碼中的顯示功能:

 

private  void ShowMessage(string message)
        {
            richTextBox1.AppendText(message + "\r\n");
            richTextBox1.ScrollToCaret();
        }

 

其次,在窗體中創建一個形參與上述ShowMessage方法相同的委託並實例化一個對象,同時創建一個線程對象,如下:

 public partial class Form1 : Form
    {
        delegate void MyDelegate(string message);
        private  MyDelegate myDeleteage;
        private Thread thread;
        ......

接着,在窗體的Form_Load事件增加一名代碼,將顯示方法搭載到委託對象上,如下:

        private void Form1_Load(object sender, EventArgs e)
        {
            myDeleteage = ShowMessage;
        }

然後,將前述的計算代碼改寫成一個窗體的成員方法。

private void Caculate()
        {
            int i = 0;
            while(true)
            {
                i = i + 2;
                this.Invoke(myDeleteage, i.ToString());
            }
        }

注意,這裏使用了Invoke方法,可以這樣理解,當需要顯示時,由窗體的Invoke方法調用委託對象,並將要顯示的內容傳遞給委託對象。而由於委託對象搭載了ShowMessage方法,所以執行this.Invoke(myDeleteage, i.ToString())語句時,實際是執行了ShowMessage(i.ToString())語句。

最後,在窗體中增加兩個按鈕,其單擊事件代碼分別如下:

 private void button1_Click(object sender, EventArgs e)
        {

            this.Invoke(myDeleteage, "begin to calculate...");
            button1.Enabled = false;
            button2.Enabled = true;
            if (thread == null)
            {
                thread = new Thread(Calculate);
                thread.Start();
            }
            if (thread.ThreadState == ThreadState.Suspended)
            {
                thread.Resume();
            }
        }
private void button2_Click(object sender, EventArgs e)
        {
           
            button2.Enabled = false;
            thread.Suspend();
            this.Invoke(myDeleteage, "Calculating is stoped.");
            button1.Enabled = true;

        }

運行程序,單擊button1,計算結果源源不斷顯示在文本框內,且界面沒有卡死,單擊button2,計算被暫停,再單擊button1,計算繼續進行。


 

 

 

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