避免一个“长操作”影响界面响应和刷新的方法。
1. Application.DoEvent()
private void button1_Click(object sender, System.EventArgs e)
{
Test(100);
} private void Test(int max)
{
this.progressBar1.Maximum = max;
while (this.progressBar1.Value < this.progressBar1.Maximum)
{
this.progressBar1.Value += 1;
Application.DoEvents();
System.Threading.Thread.Sleep(500);
}
}
2. Delegate Async
private delegate void TestHandler(int max);
private void button1_Click(object sender, System.EventArgs e)
{
TestHandler t = new TestHandler(Test);
t.BeginInvoke(100, null, null);
} private void Test(int max)
{
this.progressBar1.Maximum = max;
while (this.progressBar1.Value < this.progressBar1.Maximum)
{
this.progressBar1.Value += 1;
System.Threading.Thread.Sleep(500);
}
}
3. Thread
private void button1_Click(object sender, System.EventArgs e)
{
new Thread(new ThreadStart(ThreadProc)).Start();
} private void ThreadProc()
{
this.progressBar1.Maximum = 100;
while (this.progressBar1.Value < this.progressBar1.Maximum)
{
this.progressBar1.Value += 1;
System.Threading.Thread.Sleep(500);
}
}
上面的代码虽然能正常工作,但是违反了一个规则。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。Control.InvokeRequired属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。控件上有四种方法可以安全地从任何线程进行调用:Invoke、BeginInvoke、EndInvoke 和 CreateGraphics。对于所有其他方法调用,当从另一个线程进行调用时,应使用这些 Invoke 方法之一。(摘自SDK帮助)
修改为:
private delegate void ChangeProgressHandler(int max, int value);
private void button1_Click(object sender, System.EventArgs e)
{
new Thread(new ThreadStart(ThreadProc)).Start();
} private void ThreadProc()
{
int i = 0;
while (++i < 100)
{
this.Invoke(new ChangeProgressHandler(ChangeProgress), new object[]{100, i});
System.Threading.Thread.Sleep(500);
}
} private void ChangeProgress(int max, int value)
{
if (this.Tag == null)
{
MessageBox.Show(this.InvokeRequired.ToString());
this.Tag = 1;
} this.progressBar1.Maximum = max;
this.progressBar1.Value = value;
}