這個問題會讓一些初學者感到困惑,一方面模態窗體在打開之後(Form.ShowDialog).主線程無法繼續執行下面的事務;另一方面,又要在處理事務的時候來同步這個窗體裡面的進度條。這兩件事情都必須做,卻都不能先做...
所以很多人不得不把事務處理寫到模態窗體當中去,這樣可以達到目的,卻造成了代碼結構混亂,而且子窗體無法復用,如果有多個事物,不得不為每個事務來寫控制窗體。
這裡我們介紹一種比較直接了當的方法,就是主線程中開啟兩個子線程,一個用於顯示模態窗體,一個用於處理事務, 並同時更新第一個線程中的窗體信息。
這裡的知識范疇會包含線程的基礎用法,線程和UI之間的交互,以及委托的基本用法。如果你還不了解這幾點,可以參考一些其他資料,比如我先前寫過的,在同一窗體中用子線程來控制進度條
http://blog.csdn.net/jinjazz/archive/2008/05/06/2397136.aspx
這裡的應用稍微復雜一些,你可以先用Vs2005新建一個Windows Application,這個application包含兩個窗體,一個Form1,為主窗體,一個Form2,為模態子窗體。Form1,中添加Button1,用來開啟測試。Form2中添加進度條ProgressBar1和一個用來取消事務的按鈕Button1。然後把如下代碼貼入測試程序中的兩個form裡面。
Form1,主窗體
using System;
using System.Windows.Forms;
namespace WindowsApplication39
...{
public partial class Form1 : Form
...{
delegate void dShowForm();
Form2 frm = new Form2();
public Form1()
...{
this.InitializeComponent();
}
//顯示窗體
void ShowForm()
...{
if (this.InvokeRequired)
...{
this.Invoke(new dShowForm(this.ShowForm));
}
else
...{
frm.ShowDialog(this);
}
}
//控制進度
void SetProgress()
...{
for (int i = 1; i <= 100; i++)
...{
if (frm.DialogResult == DialogResult.Cancel)
...{
//判斷取消
break;
}
else
...{
//模擬進度
frm.SetProgress(100, i);
System.Threading.Thread.Sleep(50);
}
}
}
private void button1_Click(object sender, EventArgs e)
...{
new System.Threading.Thread(new System.Threading.ThreadStart(ShowForm)).Start();
new System.Threading.Thread(new System.Threading.ThreadStart(SetProgress)).Start();
}
}
}
Form2,模態窗體
using System;
using System.Windows.Forms;
namespace WindowsApplication39
...{
public partial class Form2 : Form
...{
public Form2()
...{
InitializeComponent();
}
public delegate void dSetProgress(int total, int current);
public void SetProgress(int total, int current)
...{
if (this.InvokeRequired)
...{
try
...{
this.Invoke(new dSetProgress(this.SetProgress), new object[] ...{ total, current });
}
catch ...{ }
}
else
...{
this.progressBar1.Maximum = total;
this.progressBar1.Value = current;
}
}
private void button1_Click(object sender, EventArgs e)
...{
this.DialogResult = DialogResult.Cancel;
}
}
}