C# 使用委託實現多執行緒呼叫窗體的四種方式
1、方法一:使用執行緒
功能描述:在用c#做WinFrom開發的過程中。我們經常需要用到進度條(ProgressBar)用於顯示進度資訊。這時候我們可能就需要用到多執行緒,如果不採用多執行緒控制進度條,視窗很容易假死(無法適時看到進度資訊)。下面我就簡單結合一個我寫的例子給大家做一個介紹。
第一步:設計介面,注意需要引用 using System.Threading;
控制元件名稱分別為:
progressBar1;label1;textBox1;button1;
第二步:定義一個代理,用於更新ProgressBar的值(Value)及在執行方法的時候,返回方法的處理資訊。
private delegate void SetPos(int ipos,string vinfo);//代理
第三步:進度條值更新函式(引數必須跟宣告的代理引數一樣)
private void SetTextMesssage(int ipos,string vinfo)
{
if (this.InvokeRequired)
{
SetPos setpos = new SetPos(SetTextMesssage);
this.Invoke(setpos, new object[] { ipos,vinfo });
}
else
{
this.label1.Text = ipos.ToString() + "/1000";
this.progressBar1.Value = Convert.ToInt32(ipos);
this.textBox1.AppendText(vinfo);
}
}
第四步:函式實現
private void button1_Click(object sender, EventArgs e)
{
Thread fThread = new Thread(new ThreadStart(SleepT));
fThread.Start();
}
第五步:新的執行緒執行函式:
private void SleepT()
{
for (int i = 0; i < 500; i++)
{
System.Threading.Thread.Sleep(10);
SetTextMesssage(100*i/500,i.ToString()+"\r\n");
}
}
程式執行效果圖:
=========================================================================================
2、第二種方法:
功能描述:該種方法通過控制元件backgroundWorker1實現,進度條。卻進度條在一個模板窗體內。
第一步:主窗體設計:
控制元件名稱:
button1;backgroundWorker1;
對backgroundWorker1控制元件,屬性設定:
第二步:主頁面後臺程式碼:
using System.Threading;//引用空間名稱
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync(); // 執行 backgroundWorker 元件
ProcessForm form = new ProcessForm(this.backgroundWorker1);// 顯示進度條窗體
form.ShowDialog(this);
form.Close();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
}
else
{
}
}
//你可以在這個方法內,實現你的呼叫,方法等。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
worker.ReportProgress(i);
if (worker.CancellationPending) // 如果使用者取消則跳出處理資料程式碼
{
e.Cancel = true;
break;
}
}
}
分別為button控制元件和backgroundWorker1控制元件選好事件。
第三步:設定子窗體(及顯示進度條的窗體):
控制元件名稱:
progressBar1;button1
第四步:子窗體,後臺程式碼:
private BackgroundWorker backgroundWorker1; //ProcessForm 窗體事件(進度條窗體)
public ProcessForm(BackgroundWorker backgroundWorker1)
{
InitializeComponent();
this.backgroundWorker1 = backgroundWorker1;
this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this.Close();//執行完之後,直接關閉頁面
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
this.button1.Enabled = false;
this.Close();
}
}
只為button選好事件
執行效果為:
=================================================================================================
3、第三種方法:
功能描述:在處理大量資料的時候,有時候方法的執行需要一定的時間,這時候往往會造成頁面或程式的“假死”狀態,給使用者的體驗度也不是很好。為了避免出現“假死”提高使用者的體驗度,在這裡為這型別的方法加了一個進度條和一個文字框,進度條用於顯示程式處理的進度,文字框用於顯示在處理過程中,給與的提示。本方法主要使用了控制元件:backgroundWorker1;說明:本方法與上面的方法(方法二)基本型別,主要是設計和程式碼進行了一些修改。
第一步:主窗體設計:
控制元件名稱:
button1;backgroundWorker1;
對backgroundWorker1控制元件,屬性設定:
第二步:主窗體 後臺程式碼:
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync(); // 執行 backgroundWorker 元件
ProcessForm form = new ProcessForm(this.backgroundWorker1);// 顯示進度條窗體
form.ShowDialog(this);
form.Close();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
}
else
{
}
}
//你可以在這個方法內,實現你的呼叫,方法等。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
worker.ReportProgress(i, i.ToString() + " 你好!\r\n"); //注意:這裡向子窗體返回資訊值,這裡是兩個值,一個用於進度條,一個用於文字框的。
if (worker.CancellationPending) // 如果使用者取消則跳出處理資料程式碼
{
e.Cancel = true;
break;
}
}
}
第三步:設定子窗體(及顯示進度條的窗體):
控制元件:
progressBar1;textBox1;button1
第四步:子窗體後臺程式碼:
private BackgroundWorker backgroundWorker1; //ProcessForm 窗體事件(進度條窗體)
public ProcessForm(BackgroundWorker backgroundWorker1)
{
InitializeComponent();
this.backgroundWorker1 = backgroundWorker1;
this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this.Close();//執行完之後,直接關閉頁面
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
this.textBox1.AppendText(e.UserState.ToString());//主窗體傳過來的值,通過e.UserState.ToString()來接受
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
this.button1.Enabled = false;
this.Close();
}
實現的效果:
注意:如果在程式為執行完,就點選取消的話,很有可能會報錯的,這時候,你就修改一個方法:backgroundWorker1_ProgressChanged
如下:
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
this.textBox1.Text += e.UserState.ToString(); //主窗體傳過來的值,通過e.UserState.ToString()來接受
}
把這個方法,替換上邊的那個方法,就可以了。
=====================================================================================================
4、第四種方法:
功能描述:本方法實現進度條顯示,方法執行資訊反饋顯示。用到的技術點為 執行緒與代理。
步驟一:新增主頁面。
控制元件名稱:
button1;
步驟二:主頁面後臺程式碼
using System.Threading;//引用此命名
//建立代理。
private Form6 myProcessBar = null;//彈出的子窗體(用於顯示進度條)
private delegate bool IncreaseHandle(int nValue,string vinfo);//代理建立
private IncreaseHandle myIncrease = null;//宣告代理,用於後面的例項化代理
private int vMax = 100;//用於例項化進度條,可以根據自己的需要,自己改變
private void button1_Click(object sender, EventArgs e)
{
Thread thdSub = new Thread(new ThreadStart(ThreadFun));
thdSub.Start();
}
private void ThreadFun()
{
MethodInvoker mi = new MethodInvoker(ShowProcessBar);
this.BeginInvoke(mi);
Thread.Sleep(100);
object objReturn = null;
for (int i = 0; i < vMax; i++)
{
objReturn = this.Invoke(this.myIncrease, new object[] { 2, i.ToString() + "\r\n" });
Thread.Sleep(50);
}
}
private void ShowProcessBar()
{
myProcessBar = new Form6(vMax);
myIncrease = new IncreaseHandle(myProcessBar.Increase);
myProcessBar.ShowDialog();
myProcessBar = null;
}
步驟三:建立子窗體
控制元件名稱:
progressBar1;textBox1
步驟四:子窗體,後臺程式碼
public Form6(int vMax)
{
InitializeComponent();
this.progressBar1.Maximum = vMax;
}
public bool Increase(int nValue,string nInfo)
{
if (nValue > 0)
{
if (progressBar1.Value + nValue < progressBar1.Maximum)
{
progressBar1.Value += nValue;
this.textBox1.AppendText(nInfo);
Application.DoEvents();
progressBar1.Update();
progressBar1.Refresh();
this.textBox1.Update();
this.textBox1.Refresh();
return true;
}
else
{
progressBar1.Value = progressBar1.Maximum;
this.textBox1.AppendText(nInfo);
//this.Close();//執行完之後,自動關閉子窗體
return false;
}
}
return false;
}
執行效果: