日韩欧美人妻无码精品白浆,夜夜嗨AV免费入口,国产欧美官网在线看,高校回应聋哑女生因长相完美被质疑

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C#中的BackgroundWorker詳解

freeflydom
2025年5月17日 9:46 本文熱度 481

在C#中,經(jīng)常會(huì)有一些耗時(shí)較長(zhǎng)的CPU密集型運(yùn)算,因?yàn)槿绻苯釉赨I線程執(zhí)行這樣的運(yùn)算就會(huì)出現(xiàn)UI不響應(yīng)的問(wèn)題。解決這類問(wèn)題的主要途徑是使用多線程,啟動(dòng)一個(gè)后臺(tái)線程,把運(yùn)算操作放在這個(gè)后臺(tái)線程中完成。但是原生接口的線程操作有一些難度,如果要更進(jìn)一步的去完成線程間的通訊就會(huì)難上加難。

因此,.NET類庫(kù)中提供了一個(gè)叫做BackgroundWorker的類可以比較優(yōu)雅的解決這類問(wèn)題。雖然BackgroundWorker類使用起來(lái)比較簡(jiǎn)單,但其中還是有一些需要注意的細(xì)節(jié),下面我們就通過(guò)一個(gè)簡(jiǎn)單的Dmeo程序,來(lái)詳細(xì)介紹它的主要用法。我們?cè)贒emo中計(jì)算1到100的累加和,為了演示效果,每次計(jì)算都睡眠600毫秒,Demo的界面如下:

用法概述:

在窗體上構(gòu)建一個(gè)BackgroundWorker實(shí)例,在它的DoWork事件處理函數(shù)中添加耗時(shí)的運(yùn)算,然后調(diào)用它的RunWorkerAsync方法就可以了。

 1  private BackgroundWorker _demoBGWorker=new BackgroundWorker();
 2  
 3  public Form1()
 4  {
 5      InitializeComponent();
 6     
 7  }
 8  
 9  private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
10  {
11      //在這里執(zhí)行耗時(shí)運(yùn)算。
12      int sum = 0;
13      for(int i = 0; i < 100; i++)
14      {
15          sum += i;
16      }
17  }
18 
19 
20  private void btnStart_Click(object sender, EventArgs e)
21  {
22      _demoBGWorker.DoWork += BGWorker_DoWork;
23      _demoBGWorker.RunWorkerAsync();
24  }

以上部分,暫時(shí)沒(méi)有加入進(jìn)度條的顯示邏輯,以及其余耗時(shí)的計(jì)算,但我們可以先考慮下面幾個(gè)問(wèn)題:

  • 如果我們要想把參數(shù)傳遞給運(yùn)算過(guò)程怎么做?
  • 在運(yùn)算過(guò)程中我們希望把實(shí)時(shí)的信息顯示在UI上應(yīng)該怎么辦?
  • 如果我們想要取消正在進(jìn)行的運(yùn)算該怎么辦?
  • 如果運(yùn)算過(guò)程出現(xiàn)異常我們又該如何處理?

接下來(lái)我們就一個(gè)一個(gè)的處理這些問(wèn)題。

一、把參數(shù)傳遞給運(yùn)算過(guò)程:

  直接把100寫(xiě)死到運(yùn)算過(guò)程中一般是不會(huì)用到的,常見(jiàn)的方式,都是客戶指定求和的范圍。因此我們?cè)谕ㄟ^(guò)調(diào)用RunWorkerAsync方法啟動(dòng)計(jì)算過(guò)程時(shí),這個(gè)方法可以接受一個(gè)object類型的參數(shù),我們可以通過(guò)它把任何數(shù)據(jù)傳遞給計(jì)算過(guò)程:

        private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //在這里執(zhí)行耗時(shí)運(yùn)算。
            int endNumber = 0;
            if (e.Argument != null)
            {
                endNumber=(int)e.Argument;
            }
            int sum = 0;
            for(int i = 0; i < endNumber; i++)
            {
                sum += i;
            }
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            _demoBGWorker.DoWork += BGWorker_DoWork;
            int num = int.Parse(numericUpDown1.Value.ToString());
            //給滾動(dòng)條賦值
            this.progressBar1.Maximum = num;
            _demoBGWorker.RunWorkerAsync(num);
        }

BGWork_DoWork事件處理函數(shù)通過(guò)參數(shù)e的Argument屬性傳來(lái)了我們期望的運(yùn)算信息。

二、把消息傳遞給UI

  由于計(jì)算過(guò)程比較長(zhǎng),我們?cè)谕ㄟ^(guò)進(jìn)度條來(lái)顯示當(dāng)前進(jìn)度的同時(shí),還希望能實(shí)時(shí)的把計(jì)算的中間愛(ài)結(jié)果顯示在UI上。當(dāng)然,BackgroundWorker對(duì)這個(gè)用例也提供了很好的支持。它允許我們?cè)趫?zhí)行計(jì)算的過(guò)程中給UI線程發(fā)送消息,下面看看具體的做法:

 private void btnStart_Click(object sender, EventArgs e)
 {
     _demoBGWorker.DoWork += BGWorker_DoWork;
     int num = int.Parse(numericUpDown1.Value.ToString());
     //給滾動(dòng)條賦值
     this.progressBar1.Maximum = num;
     _demoBGWorker.RunWorkerAsync(num);
     _demoBGWorker.WorkerReportsProgress = true;
     _demoBGWorker.ProgressChanged += BGWorker_ProgressChanged;
 }

  首先要把WorkerReportsProgress屬性設(shè)置為true,然后為ProgressChanged事件添加處理方法:

private void BGWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
{
    //修改進(jìn)度條的顯示。
    this.progressBar1.Value=e.ProgressPercentage;
    //如果有更多的信息需要傳遞,可以使用 e.UserState傳遞一個(gè)自定義的類型。
    //這是一個(gè)object類型的對(duì)象,您可以通過(guò)它傳遞任何類型。
    //我們僅把當(dāng)前sum的值通過(guò)e.UserState傳回,并通過(guò)顯示在窗口上。
    string message =e.UserState.ToString();
    this.lblSum.Text = message;
}

繼續(xù)更新BGWorker_DoWork方法:

private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bgWorker=sender as BackgroundWorker;
    //在這里執(zhí)行耗時(shí)運(yùn)算。
    int endNumber = 0;
    if (e.Argument != null)
    {
        endNumber=(int)e.Argument;
    }
    int sum = 0;
    for(int i = 0; i < endNumber; i++)
    {
        sum += i;
        string message = $"Current sum is:{sum}";
        //ReportProgress 方法把信息傳遞給ProcessChanged事件處理函數(shù)。
        //第一個(gè)參數(shù)類型為 int,表示執(zhí)行進(jìn)度。
        //如果有更多的信息需要傳遞,可以使用ReportProgress的第二個(gè)參數(shù)。
        //這里我們給第二個(gè)參數(shù)傳進(jìn)去一條消息。
        bgWorker.ReportProgress(i, message);
        Thread.Sleep(600);
    }
}

現(xiàn)在,我們已經(jīng)可以看到進(jìn)度條和執(zhí)行信息的更新了。

三、取消操作

  在執(zhí)行過(guò)程中允許用戶取消當(dāng)前的操作是一個(gè)基本的設(shè)計(jì),BackgroundWorker自然有很好的支持:

 _demoBGWorker.WorkerSupportsCancellation = true;

  和WorkerReportsProgress屬性一樣,如果要支持取消操作,我們需要設(shè)置WorkerSupportsCancellation屬性為true。并且還要在BGWorker_DoWork方法中進(jìn)行支持,在for循環(huán)中Thread.Sleep(600)后面添加代碼:

 bgWorker.ReportProgress(i, message);
 Thread.Sleep(600);
 //在操作的過(guò)程中需要檢查用戶是否取消了當(dāng)前的操作。
 if (bgWorker.CancellationPending == true)
 {
     e.Cancel = true;
     break;
 }

如果檢測(cè)到用戶點(diǎn)擊的取消按鈕,就退出當(dāng)前的計(jì)算過(guò)程,下面是點(diǎn)擊取消按鈕時(shí)要調(diào)用的代碼:

private void btnCancel_Click(object sender, EventArgs e)
{
    _demoBGWorker.CancelAsync();
}

四、異常處理

  如果在計(jì)算過(guò)程中發(fā)生了異常應(yīng)該怎么處理?有沒(méi)有辦法知道計(jì)算過(guò)程已經(jīng)結(jié)束?當(dāng)然要有,即便是正常的結(jié)束也需要拿到計(jì)算的結(jié)果。

private void btnStart_Click(object sender, EventArgs e)
{
    _demoBGWorker.DoWork += BGWorker_DoWork;
    int num = int.Parse(numericUpDown1.Value.ToString());
    //給滾動(dòng)條賦值
    this.progressBar1.Maximum = num;
    _demoBGWorker.RunWorkerAsync(num);
    _demoBGWorker.WorkerSupportsCancellation = true;
    _demoBGWorker.WorkerReportsProgress = true;
    _demoBGWorker.ProgressChanged += BGWorker_ProgressChanged;
    _demoBGWorker.RunWorkerCompleted += BGWorker_RunWorkerCompleted;
}
private void BGWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //如果用戶取消了當(dāng)前操作就關(guān)閉窗口。
    if (e.Cancelled)
    {
        this.Close();
    }
    //計(jì)算已經(jīng)結(jié)束,需要禁用取消按鈕。
    this.btnCancel.Enabled = false;
    //計(jì)算過(guò)程中的異常會(huì)被抓住,在這里可以進(jìn)行處理。
    if (e.Error != null)
    {
        Type errorType = e.Error.GetType();
        switch (errorType.Name)
        {
            case "ArgumentNullExcepetion":
            case "MyException":
                //do something.
                break;
            default:
                //do something.
                break;
        }
    }
    //計(jì)算結(jié)果信息:e.Result
    //use it do something.
}

RunWorkerCompleted事件處理函數(shù)會(huì)在DoWork事件處理函數(shù)返回后被調(diào)用。通過(guò)它我們可以進(jìn)行一些運(yùn)算結(jié)束后的操作,比如禁用取消按鈕,異常處理,結(jié)果顯示等。

注意,如果想要拿到e.Result,您需要在BGWorker_DoWork方法中設(shè)置e.Result屬性,如:

e.Result=sum;

總結(jié),BackgroundWorker類功能完善且使用簡(jiǎn)便,非常適合處理異步耗時(shí)的操作。

轉(zhuǎn)自https://www.cnblogs.com/Sheldon180621/p/18245692


該文章在 2025/5/17 9:46:00 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved