假設在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,計算繼續進行。