這個問題會讓一些初學者感到困惑,一方面模態窗體在打開之後(Form.ShowDialog).主線程無法繼續執行下面的事務;另一方面,又要在處理事務的時候來同步這個窗體裏面的進度條。這兩件事情都必須做,卻都不能先做...
所以很多人不得不把事務處理寫到模態窗體當中去,這樣可以達到目的,卻造成了代碼結構混亂,而且子窗體無法複用,如果有多個事物,不得不爲每個事務來寫控制窗體。
這裏我們介紹一種比較直接了當的方法,就是主線程中開啓兩個子線程,一個用於顯示模態窗體,一個用於處理事務, 並同時更新第一個線程中的窗體信息。
這裏的知識範疇會包含線程的基礎用法,線程和UI之間的交互,以及委託的基本用法。如果你還不瞭解這幾點,可以參考一些其他資料,比如我先前寫過的,在同一窗體中用子線程來控制進度條
這裏的應用稍微複雜一些,你可以先用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();
}
}
}
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;
}
}
}