實戰.Net多執行緒(三)
BackgroundWorker類在 .NET Framework 2.0 中是新增的,它能夠在單獨的執行緒上執行特定操作。
關於BackgroundWorker的基本使用方法我們不在這裡說明,在MSDN中已經有了很詳細的介紹,並且還有個關於如何使用 BackgroundWorker 類非同步執行耗時操作的示例,該示例是計算選定的斐波納契數、在計算過程中報告進度更新,並允許取消掛起的計算等。這個例子很基礎:在主窗體中有兩個button,一個用於啟動BackgroundWorker的執行,另一個用於取消,而進度條指示是在主窗體上顯示,縱觀這個示例並不是特別適用於實際使用。而我們則需要更多的功能,並且製作出接近實際使用的示例!
我們的目標有兩個,1、啟動和終止執行緒要在一個button內完成;2、需要在另一個單獨的窗體中顯示耗時操作的進度。解決第一個問題需要在button單擊事件需要判斷BackgroundWorker類的例項是否已建立,然後需要檢測BackgroundWorker的一個屬性IsBusy,當IsBusy=true時說明BackgroundWorker正在後臺進行處理,否則可以重新開始一個後臺操作,程式碼如下:
private BackgroundWorker m_AsyncWorker1 = null;
private void button4_Click(object sender, EventArgs e)
{
if (m_AsyncWorker1 == null)
{
m_AsyncWorker1 = new BackgroundWorker();
m_AsyncWorker1.WorkerReportsProgress = true;
m_AsyncWorker1.WorkerSupportsCancellation = true;
m_AsyncWorker1.ProgressChanged += new ProgressChangedEventHandler(m_AsyncWorker1_ProgressChanged);
m_AsyncWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_AsyncWorker1_RunWorkerCompleted);
m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);
}
if (m_AsyncWorker1.IsBusy)
{
button4.Enabled = false;
button4.Text = "Canceling, Please wait....";
m_AsyncWorker1.CancelAsync();
}
else
{
button4.Text = "Cancel";
m_AsyncWorker1.RunWorkerAsync();
}
}
我們的示例是建立一個隨機數,然後從0開始遍歷這個隨機數,並且通過在主窗體上的Label和ProgressBar呈現出迴圈的進度。
ProgressChanged、RunWorkerCompleted和DoWork是BackgroundWorker的最重要的事件,我們可以按照方法指標型別來對待它,因為其實它就是一個委託型別,為了驗證DoWork是委託型別,有一個最簡單方法,就是在IDE的文字編輯器中的DoWork上右鍵"轉到定義",這時會看到DoWork是DoWorkEventHandler型別的事件,這當然沒錯!然後繼續在DoWorkEventHandler上右鍵"轉到定義",這時我們就會經意的發現:
public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e);
原來事件的基本形態還是委託!所以在 .Net 下事件和委託是不可分割的兩種型別!!過一段時間我會特別寫博文來和大家一起專門試驗和探討.Net事件和委託。
知道了是方法指標型別,我們就可以按照地址的形式賦予DoWork事件被激發時需要執行的操作的方法地址,亦即:
m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);
好了,扯得稍微有點遠了。我們繼續看ProgressChanged、RunWorkerCompleted和DoWork的實際內容,程式碼如下:
private void m_AsyncWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bwAsync = sender as BackgroundWorker;
int iCount = new Random().Next(20, 50);
for (int i = 0; i < iCount; i++)
{
Thread.Sleep(100);
bwAsync.ReportProgress(Convert.ToInt32(i * (100.0 / iCount)));
if (bwAsync.CancellationPending)
{
Thread.Sleep(1200);
e.Cancel = true;
return;
}
}
bwAsync.ReportProgress(100);
}
private void m_AsyncWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label1.Text = e.ProgressPercentage.ToString() + "%";
}
private void m_AsyncWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button4.Text = "Start";
progressBar1.Value = 0;
button4.Enabled = true;
if (e.Error != null)
{
MessageBox.Show(this, e.Error.Message);
return;
}
if (e.Cancelled)
{
//Cancelled...
}
else
{
//Completed...
}
m_AsyncWorker1 = null;
}
在MSDN中關於取消後臺操作的程式碼過於基礎,不太利於實際使用。取消後臺操作大家都知道需要呼叫m_AsyncWorker1.CancelAsync(),而在DoWork遍歷數字的迴圈體內我們隨時檢測bwAsync.CancellationPending的狀態,若CancellationPending=true,說明使用者已經第二次單擊了button,亦即執行了m_AsyncWorker1.CancelAsync() ,這是需要告知BackgroundWorker準備中止操作,即e.Cancel=true。
不管是中途取消還是順利完成後臺操作,RunWorkerCompleted事件都要最後執行,所以在這段程式碼中必需檢測後臺操作是否已取消還是順利完成,然後新增相應的程式碼。
在下一篇博文中我們會繼續利用BackgroundWorker來建立更加專業的在獨立窗體中顯示後臺操作進度,以及終止後臺操作的示例。
關於BackgroundWorker的基本使用方法我們不在這裡說明,在MSDN中已經有了很詳細的介紹,並且還有個關於如何使用 BackgroundWorker 類非同步執行耗時操作的示例,該示例是計算選定的斐波納契數、在計算過程中報告進度更新,並允許取消掛起的計算等。這個例子很基礎:在主窗體中有兩個button,一個用於啟動BackgroundWorker的執行,另一個用於取消,而進度條指示是在主窗體上顯示,縱觀這個示例並不是特別適用於實際使用。而我們則需要更多的功能,並且製作出接近實際使用的示例!
我們的目標有兩個,1、啟動和終止執行緒要在一個button內完成;2、需要在另一個單獨的窗體中顯示耗時操作的進度。解決第一個問題需要在button單擊事件需要判斷BackgroundWorker類的例項是否已建立,然後需要檢測BackgroundWorker的一個屬性IsBusy,當IsBusy=true時說明BackgroundWorker正在後臺進行處理,否則可以重新開始一個後臺操作,程式碼如下:
private BackgroundWorker m_AsyncWorker1 = null;
private void button4_Click(object sender, EventArgs e)
{
if (m_AsyncWorker1 == null)
{
m_AsyncWorker1 = new BackgroundWorker();
m_AsyncWorker1.WorkerReportsProgress = true;
m_AsyncWorker1.WorkerSupportsCancellation = true;
m_AsyncWorker1.ProgressChanged += new ProgressChangedEventHandler(m_AsyncWorker1_ProgressChanged);
m_AsyncWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_AsyncWorker1_RunWorkerCompleted);
m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);
}
if (m_AsyncWorker1.IsBusy)
{
button4.Enabled = false;
button4.Text = "Canceling, Please wait....";
m_AsyncWorker1.CancelAsync();
}
else
{
button4.Text = "Cancel";
m_AsyncWorker1.RunWorkerAsync();
}
}
我們的示例是建立一個隨機數,然後從0開始遍歷這個隨機數,並且通過在主窗體上的Label和ProgressBar呈現出迴圈的進度。
ProgressChanged、RunWorkerCompleted和DoWork是BackgroundWorker的最重要的事件,我們可以按照方法指標型別來對待它,因為其實它就是一個委託型別,為了驗證DoWork是委託型別,有一個最簡單方法,就是在IDE的文字編輯器中的DoWork上右鍵"轉到定義",這時會看到DoWork是DoWorkEventHandler型別的事件,這當然沒錯!然後繼續在DoWorkEventHandler上右鍵"轉到定義",這時我們就會經意的發現:
public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e);
原來事件的基本形態還是委託!所以在 .Net 下事件和委託是不可分割的兩種型別!!過一段時間我會特別寫博文來和大家一起專門試驗和探討.Net事件和委託。
知道了是方法指標型別,我們就可以按照地址的形式賦予DoWork事件被激發時需要執行的操作的方法地址,亦即:
m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);
好了,扯得稍微有點遠了。我們繼續看ProgressChanged、RunWorkerCompleted和DoWork的實際內容,程式碼如下:
private void m_AsyncWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bwAsync = sender as BackgroundWorker;
int iCount = new Random().Next(20, 50);
for (int i = 0; i < iCount; i++)
{
Thread.Sleep(100);
bwAsync.ReportProgress(Convert.ToInt32(i * (100.0 / iCount)));
if (bwAsync.CancellationPending)
{
Thread.Sleep(1200);
e.Cancel = true;
return;
}
}
bwAsync.ReportProgress(100);
}
private void m_AsyncWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label1.Text = e.ProgressPercentage.ToString() + "%";
}
private void m_AsyncWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button4.Text = "Start";
progressBar1.Value = 0;
button4.Enabled = true;
if (e.Error != null)
{
MessageBox.Show(this, e.Error.Message);
return;
}
if (e.Cancelled)
{
//Cancelled...
}
else
{
//Completed...
}
m_AsyncWorker1 = null;
}
在MSDN中關於取消後臺操作的程式碼過於基礎,不太利於實際使用。取消後臺操作大家都知道需要呼叫m_AsyncWorker1.CancelAsync(),而在DoWork遍歷數字的迴圈體內我們隨時檢測bwAsync.CancellationPending的狀態,若CancellationPending=true,說明使用者已經第二次單擊了button,亦即執行了m_AsyncWorker1.CancelAsync() ,這是需要告知BackgroundWorker準備中止操作,即e.Cancel=true。
不管是中途取消還是順利完成後臺操作,RunWorkerCompleted事件都要最後執行,所以在這段程式碼中必需檢測後臺操作是否已取消還是順利完成,然後新增相應的程式碼。
在下一篇博文中我們會繼續利用BackgroundWorker來建立更加專業的在獨立窗體中顯示後臺操作進度,以及終止後臺操作的示例。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14325734/viewspace-426849/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 實戰.Net多執行緒(一)執行緒
- 實戰.Net多執行緒(二)執行緒
- 實戰.Net多執行緒(四)執行緒
- Java多執行緒之守護執行緒實戰Java執行緒
- .NET 多執行緒執行緒
- 多執行緒(三)執行緒
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 多執行緒系列(三):執行緒池基礎執行緒
- C#中的執行緒(三)多執行緒C#執行緒
- Java多執行緒【三種實現方法】Java執行緒
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- .NET多執行緒程式設計(1):多工和多執行緒 (轉)執行緒程式設計
- .NET下多執行緒初探執行緒
- Java多執行緒(三):SynchronizedJava執行緒synchronized
- 多執行緒筆記 三執行緒筆記
- Java實現多執行緒的三種方式Java執行緒
- .NET多執行緒程式設計(3):執行緒同步 (轉)執行緒程式設計
- 實驗--多執行緒執行緒
- 多執行緒和多執行緒同步執行緒
- Java 多執行緒學習筆記(三)-守護執行緒Java執行緒筆記
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- Java多執行緒——執行緒Java執行緒
- 執行緒與多執行緒執行緒
- VC多執行緒 C++ 多執行緒執行緒C++
- 如何實現多執行緒執行緒
- 多執行緒原理實現執行緒
- c++11 新特性實戰 (一):多執行緒操作C++執行緒
- 實戰體會Java的多執行緒程式設計Java執行緒程式設計
- 多執行緒實現多工二執行緒
- 多執行緒實現多工一執行緒
- 多執行緒-執行緒控制之休眠執行緒執行緒
- 多執行緒-執行緒控制之加入執行緒執行緒
- 多執行緒-執行緒控制之禮讓執行緒執行緒
- 多執行緒-執行緒控制之中斷執行緒執行緒
- Java併發實戰一:執行緒與執行緒安全Java執行緒
- 多執行緒(三)、執行緒池 ThreadPoolExecutor 知識點總結執行緒thread