假设在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,计算继续进行。