轉載:https://www.cnblogs.com/tohen/p/7644682.html
BackgroundWorker是微軟的在.net Framwork中添加的一個組件,主要對線程的訪問提供了一種安全的方式。簡單的說就是對Thread的一次封裝。
BackgroundWorker位於System.ComponentModel下,是一個繼承了Component的組件,微軟官方的解釋爲:Executes an operation on a separate thread.就是說,開始一個新的線程執行操作。
首先介紹一下BackgroundWorker的相關屬性和方法:
屬性:
WorkerReportsProgress:是否可以報告進度。
WorkerSupportsCancellation:是否允許異步中止。
IsBusy:是否在運行。
CancellationPending:判斷BackgroundWorker是否已經異步取消。
方法:
RunWorkerAsync:開始執行任務。觸發DoWork事件
ReportProgress:異步提醒,觸發ProgressChanged事件,但是這個如果可以使用,必須設置WorkerReportsProgress爲True
CancelAsync:取消BackgroundWorker操作。
事件:
DoWork:執行RunWorkerAsync後觸發,異步執行的認爲。
ProgressChanged:執行ReportProgress時觸發,異步獲得進度。
RunWorkerCompleted:線程結束時觸發,主要有成功結束,發生異常或者取消時發生。
Thread相對來說就簡單了,但是使用起來就比較麻煩了。Thread位於System.Threading的名空間下,是一個可以獨立創建和操作一個線程,並且對線程進行設置優先級和獲得狀態的一個不可繼承的類。
下面是我做的一個例子,來比較他們兩個的使用。
建立一個窗體,放置了兩個TextBox,分別爲設置開始和結束的Progree的值,放置兩個ProgressBar,分別設置爲線程的Progressbar和BackGroundWorker的ProgressBar。另外放置按鈕爲StartBackGroundWorker,StartThread,CancelBackGroundWorker,CancelThread和PauseThread。
BackGroundWorker的使用就非常簡單:
/// <summary>
/// Handles the Click event of the btnBackGroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnBackGroundWorker_Click(object sender, EventArgs e)
{
StartFrom = Convert.ToInt32(txtStart.Text);
EndTo = Convert.ToInt32(txtEnd.Text);
progressBarThread.Minimum = StartFrom;
progressBarThread.Maximum = EndTo;
this.btnBackGroundWorker.Enabled = false;
this.backgroundWorker.RunWorkerAsync();
}
/// <summary>
/// Handles the DoWork event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
if (this.backgroundWorker.CancellationPending)
{
e.Cancel = true;
return;
}
this.backgroundWorker.ReportProgress(nValue);
Thread.Sleep(200);
}
}
/// <summary>
/// Handles the ProgressChanged event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.prgProcessBackGroundWorker.Value = e.ProgressPercentage;
}
/// <summary>
/// Handles the RunWorkerCompleted event of the backgroundWorker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 取消
if (e.Cancelled)
{
MessageBox.Show("Cancelled");
}
// 出現錯誤
else if (e.Error != null)
{
MessageBox.Show(e.Error.Message + Environment.NewLine + e.Error.StackTrace);
}
// 完成
else
{
MessageBox.Show("Completed");
this.btnBackGroundWorker.Enabled = true;
}
}
/// <summary>
/// Handles the Click event of the btnCancelBackgroundWoker control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnCancelBackgroundWoker_Click(object sender, EventArgs e)
{
this.backgroundWorker.CancelAsync();
}
Thread的使用就比較麻煩了,對於尤其是對異步提醒來說,需要寫委託,代碼量是很多,但是對於BackgroundWorker來說,卻沒有線程暫停和繼續的方法。但是對於一般的來說,這些功能也是不用的,而且在微軟的文檔中還提到了,Thread的Resume和Suspend已經不推薦使用。
// 聲明委託
delegate void DelegateType(int x);
DelegateType TheDelegate;
// ProgressBar的開始和結束值
int StartFrom, EndTo;
// 是否線程暫停
bool IsThreadPaused;
ManualResetEvent CancelEvent = new ManualResetEvent(false);
Thread MyThread;
/// <summary>
/// 委託的消息事件
/// </summary>
/// <param name="nProgress">進度值</param>
private void MessageHandler(int nProgress)
{
lblThreadStatus.Text = "處理: " + Convert.ToString(nProgress);
progressBarThread.Value = nProgress;
if (nProgress == progressBarThread.Maximum)
{
MessageBox.Show("Completed");
this.btnTread.Enabled = true;
}
}
/// <summary>
/// Handles the Click event of the btnTread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnTread_Click(object sender, EventArgs e)
{
TheDelegate = MessageHandler;
StartFrom = Convert.ToInt32(txtStart.Text);
EndTo = Convert.ToInt32(txtEnd.Text);
progressBarThread.Minimum = StartFrom;
progressBarThread.Maximum = EndTo;
btnTread.Enabled = false;
IsThreadPaused = false;
MyThread = new Thread(ProcessRoutine);
MyThread.Start();
}
/// <summary>
/// Processes the routine.
/// </summary>
private void ProcessRoutine()
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
// 判斷是否取消
if (CancelEvent.WaitOne(0, false) == true)
{
return;
}
this.BeginInvoke(this.TheDelegate, nValue);
Thread.Sleep(200);
}
}
/// <summary>
/// Handles the Click event of the btnCancelThread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnCancelThread_Click(object sender, EventArgs e)
{
btnCancelThread.Enabled = false;
btnPauseThread.Enabled = false;
CancelEvent.Set();
MyThread.Join();
}
/// <summary>
/// Handles the Click event of the btnPauseThread control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void btnPauseThread_Click(object sender, EventArgs e)
{
// Bad approach!
if (!IsThreadPaused)
{
IsThreadPaused = true;
MyThread.Suspend();
btnPauseThread.Text = "Resume Thread";
// Disallow Cancel
btnCancelThread.Enabled = false;
}
else
{
IsThreadPaused = false;
MyThread.Resume();
btnPauseThread.Text = "Pause Thread";
btnCancelThread.Enabled = true;
}
}