winform多線程組件BackgroundWorker使用
BackgroundWorker是·net里用來(lái)執(zhí)行多線程任務(wù)的控件,它允許編程者在一個(gè)單獨(dú)的線程上執(zhí)行一些操作。
可以通過(guò)編程方式創(chuàng)建 BackgroundWorker,也可以將它從“工具箱”的“組件”選項(xiàng)卡中拖到窗體上。 如果在 Windows 窗體設(shè)計(jì)器中創(chuàng)建 BackgroundWorker,則它會(huì)出現(xiàn)在組件欄中,而且它的屬性會(huì)顯示在“屬性”窗口中。
常用方法
- RunWorkerAsync 開(kāi)始執(zhí)行后臺(tái)操作。引發(fā) DoWork 事件。
public void RunWorkerAsync(); //啟動(dòng)線程,觸發(fā)DoWork事件
public void RunWorkerAsync(object argument); - CancelAsync 請(qǐng)求取消掛起的后臺(tái)操作。
注意:這個(gè)方法是將 CancellationPending 屬性設(shè)置為 true,并不會(huì)終止后臺(tái)操作。在后臺(tái)操作中要檢查CancellationPending 屬性,來(lái)決定是否要繼續(xù)執(zhí)行耗時(shí)的操作。 - ReportProgress引發(fā) ProgressChanged 事件。
public void ReportProgress(int percentProgress); //報(bào)告進(jìn)度,觸發(fā)ProgressChanged事件
public void ReportProgress(int percentProgress, object userState);
常用屬性
- IsBusy: //只讀屬性,用來(lái)判斷當(dāng)前線程是否正在工作中。
- CancellationPending: 指示應(yīng)用程序是否已請(qǐng)求取消后臺(tái)操作。只讀屬性,默認(rèn)為 false,當(dāng)執(zhí)行了 CancelAsync 方法后,值為 true。
- WorkerSupportsCancellation:指示是否支持異步取消。要執(zhí)行 CancelAsync 方法,需要先設(shè)置該屬性為 true。
- WorkerReportsProgress:指示是否能報(bào)告進(jìn)度。要執(zhí)行 ReportProgress 方法,需要先設(shè)置該屬性為 true。
常用事件
- DoWork: 調(diào)用 RunWorkerAsync 方法時(shí)發(fā)生。
- ProgressChanged:可選,調(diào)用 ReportProgress 方法時(shí)發(fā)生。
- RunWorkerCompleted:可選,后臺(tái)操作已完成、被取消或引發(fā)異常時(shí)發(fā)生。
注意:在 DoWork 事件處理程序中不操作任何用戶界面對(duì)象。而應(yīng)該通過(guò) ProgressChanged 和RunWorkerCompleted 事件與用戶界面進(jìn)行通信。
如果想在 DoWork 事件處理程序中和用戶界面的控件通信,可在用 ReportProgress 方法。ReportProgress(int percentProgress, object userState),可以傳遞一個(gè)對(duì)象。ProgressChanged 事件可以從參數(shù)ProgressChangedEventArgs 類的UserState 屬性得到這個(gè)信息對(duì)象。這個(gè)事件也可以實(shí)現(xiàn)進(jìn)度條功能,把任務(wù)的進(jìn)度實(shí)時(shí)呈現(xiàn)給用戶。
簡(jiǎn)單的程序用BackgroundWorker 比 Thread 方便,Thread中和用戶界面上的控件通信比較麻煩,需要用委托來(lái)調(diào)用控件的 Invoke 或BeginInvoke 方法,沒(méi)有 BackgroundWorker 方便。
使用backgroundWorker步驟
新建BackgroundWorder對(duì)象;
根據(jù)需求, 設(shè)置是否能取消(WorkerSupportsCancellation)、是否報(bào)告進(jìn)度(WorkerReportsProgress);
根據(jù)需求,設(shè)置好相關(guān)事件,DoWorker、ProgressChanged、ProgressChanged;
調(diào)用RunWorkerAsyns()方法,啟動(dòng)線程;
在需要取消的位置,判斷CancellationPending的值,并做相關(guān)處理;//可選
在適當(dāng)?shù)奈恢谜{(diào)用ReportProgress(int percentProgress)方法,報(bào)告進(jìn)度。
BackgroundWorker實(shí)例
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;//報(bào)告完成進(jìn)度
backgroundWorker1.WorkerSupportsCancellation = true;//允許用戶終止后臺(tái)線程
//綁定事件
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
}
//開(kāi)始按鈕
private void button1_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)//判斷backgroundWorker1是否正在運(yùn)行異步操作
{
backgroundWorker1.RunWorkerAsync(1000);//開(kāi)始執(zhí)行后臺(tái)異步操作,調(diào)用DoWork事件
}
while (backgroundWorker1.IsBusy)//等待后臺(tái)運(yùn)行完畢
{
Application.DoEvents();
}
MessageBox.Show("操作完成");
}
//取消按鈕
private void button2_Click(object sender, EventArgs e)
{
if (backgroundWorker1.WorkerSupportsCancellation == true)
{
backgroundWorker1.CancelAsync();//取消后臺(tái)操作
backgroundWorker1.Dispose();//釋放資源
}
}
//DoWork事件聲明要執(zhí)行的耗時(shí)操作
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker backgroundWorker = sender as BackgroundWorker;
e.Result = ListNumber(backgroundWorker, e);//運(yùn)算結(jié)果保存在e.Result中(在RunWorkerCompleted事件可能會(huì)使用到)
}
bool ListNumber(object sender, DoWorkEventArgs e)
{
int num = (int)e.Argument;//接收傳入的參數(shù),即RunWorkerAsync(object argument)傳入的值
for (int i = 1; i <= num; i++)
{
if (backgroundWorker1.CancellationPending)//判斷是否請(qǐng)求了取消后臺(tái)操作,如果為false則退出
{
e.Cancel = true;//e.Cancel 是否應(yīng)該取消事件
return false;
}
Thread.Sleep(10);//執(zhí)行一個(gè)耗時(shí)操作
backgroundWorker1.ReportProgress(i * 100 / num, i);//報(bào)告完成進(jìn)度
}
return true;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;//將完成進(jìn)度數(shù)據(jù)傳給進(jìn)度條
label1.Text = e.ProgressPercentage + "%";
//將中間計(jì)算結(jié)果在ListBox控件中顯示出來(lái)
listBox1.Items.Add(e.UserState);//接收ReportProgress方法傳遞過(guò)來(lái)的userState
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true) //e.Cancelled指示異步操作是否已被取消
{
MessageBox.Show("Canceled!");
}
else if (e.Error != null) //e.Error 指示異步操作期間發(fā)生的錯(cuò)誤
{
MessageBox.Show("Error: " + e.Error.Message);
}
else
{
MessageBox.Show(e.Result.ToString()); //e.Result 獲取異步操作結(jié)果的值,即DoWork事件中,Result設(shè)置的值。
}
}
}對(duì)Winform窗體控件進(jìn)行安全調(diào)用
(WinForm中實(shí)現(xiàn)多線程的首選方法是backgroundWorker)
Thread thread = new Thread(SetLabel);//另開(kāi)一個(gè)線程上設(shè)置Label的屬性
thread.Start();
delegate void Action(string args);//Net3.5自帶的Action無(wú)參數(shù)無(wú)返回值
private void SetLabel()
{
Action action = delegate (string args)
{
this.label1.Text = args;
};
if (this.InvokeRequired)//判斷當(dāng)前代碼是運(yùn)行于創(chuàng)建該控件的線程之上,還是運(yùn)行于另一個(gè)線程之上。
this.Invoke(action, "XXX");//注意控件的Inovoke和BeginInvoke委托的方法都執(zhí)行在UI線程上。對(duì)Control的Invoke方法可以使用一個(gè)簡(jiǎn)單的系統(tǒng)委托MethodInvoker無(wú)參數(shù)返回Void調(diào)用。
else
action("XXX");
}到此這篇關(guān)于winform多線程組件BackgroundWorker的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- WinForm中BackgroundWorker控件用法簡(jiǎn)單實(shí)例
- C#使用BackgroundWorker控件
- c# BackgroundWorker組件的作用
- C#中backgroundWorker類的用法詳解
- c# BackgroundWorker使用方法
- C# BackgroundWorker使用教程
- C#使用后臺(tái)線程BackgroundWorker處理任務(wù)的總結(jié)
- C# BackgroundWorker用法詳解
- C#在后臺(tái)運(yùn)行操作(BackgroundWorker用法)示例分享
- C# BackgroundWorker組件學(xué)習(xí)入門(mén)介紹
- 簡(jiǎn)單使用BackgroundWorker創(chuàng)建多個(gè)線程的教程
- C#中BackgroundWorker類用法總結(jié)
- C#中backgroundworker的使用教程
- c#異步操作后臺(tái)運(yùn)行(backgroundworker類)示例
相關(guān)文章
C# 通過(guò) inline-asm 解決嵌入x86匯編
此篇文章通過(guò)C#語(yǔ)言解決嵌入x86匯編,主要通過(guò)INline-asm方法來(lái)實(shí)現(xiàn),下面我通過(guò)圖片和代碼的形式給大家分享下,需要的朋友可以參考下2015-07-07
c#和javascript函數(shù)相互調(diào)用示例分享
在webBrowser使用過(guò)程中為了C#和JS通訊,webBrowser必須設(shè)置ObjectForScripting的屬性,它是一個(gè)object,這個(gè)object可以提供給webBrowser控件載入的網(wǎng)頁(yè)上的script訪問(wèn)2014-01-01
C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼
這篇文章主要介紹了C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-04-04
C#中DataTable和List互轉(zhuǎn)的示例代碼
很多場(chǎng)景下,我們需要將List轉(zhuǎn)換成為DataTable,本文主要介紹了C#中DataTable和List互轉(zhuǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
C# FileStream實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳
這篇文章主要為大家詳細(xì)介紹了C# FileStream實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
c# 連接access數(shù)據(jù)庫(kù)config配置
c# 連接access數(shù)據(jù)庫(kù)config配置,需要的朋友可以參考一下2013-02-02
C#實(shí)現(xiàn)掃描局域網(wǎng)內(nèi)的所有IP和端口
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)掃描局域網(wǎng)內(nèi)的所有IP和端口的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12

