男女做爽爽爽网站-男女做羞羞高清-男女做爰高清无遮挡免费视频-男女做爰猛烈-男女做爰猛烈吃奶啪啪喷水网站-内射白浆一区

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

C#中的BackgroundWorker詳解

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

在C#中,經(jīng)常會有一些耗時較長的CPU密集型運算,因為如果直接在UI線程執(zhí)行這樣的運算就會出現(xiàn)UI不響應(yīng)的問題。解決這類問題的主要途徑是使用多線程,啟動一個后臺線程,把運算操作放在這個后臺線程中完成。但是原生接口的線程操作有一些難度,如果要更進一步的去完成線程間的通訊就會難上加難。

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

用法概述:

在窗體上構(gòu)建一個BackgroundWorker實例,在它的DoWork事件處理函數(shù)中添加耗時的運算,然后調(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í)行耗時運算。
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ù)傳遞給運算過程怎么做?
  • 在運算過程中我們希望把實時的信息顯示在UI上應(yīng)該怎么辦?
  • 如果我們想要取消正在進行的運算該怎么辦?
  • 如果運算過程出現(xiàn)異常我們又該如何處理?

接下來我們就一個一個的處理這些問題。

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

  直接把100寫死到運算過程中一般是不會用到的,常見的方式,都是客戶指定求和的范圍。因此我們在通過調(diào)用RunWorkerAsync方法啟動計算過程時,這個方法可以接受一個object類型的參數(shù),我們可以通過它把任何數(shù)據(jù)傳遞給計算過程:

        private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //在這里執(zhí)行耗時運算。
            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());
            //給滾動條賦值
            this.progressBar1.Maximum = num;
            _demoBGWorker.RunWorkerAsync(num);
        }

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

二、把消息傳遞給UI

  由于計算過程比較長,我們在通過進度條來顯示當(dāng)前進度的同時,還希望能實時的把計算的中間愛結(jié)果顯示在UI上。當(dāng)然,BackgroundWorker對這個用例也提供了很好的支持。它允許我們在執(zhí)行計算的過程中給UI線程發(fā)送消息,下面看看具體的做法:

 private void btnStart_Click(object sender, EventArgs e)
 {
     _demoBGWorker.DoWork += BGWorker_DoWork;
     int num = int.Parse(numericUpDown1.Value.ToString());
     //給滾動條賦值
     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)
{
    //修改進度條的顯示。
    this.progressBar1.Value=e.ProgressPercentage;
    //如果有更多的信息需要傳遞,可以使用 e.UserState傳遞一個自定義的類型。
    //這是一個object類型的對象,您可以通過它傳遞任何類型。
    //我們僅把當(dāng)前sum的值通過e.UserState傳回,并通過顯示在窗口上。
    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í)行耗時運算。
    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ù)。
        //第一個參數(shù)類型為 int,表示執(zhí)行進度。
        //如果有更多的信息需要傳遞,可以使用ReportProgress的第二個參數(shù)。
        //這里我們給第二個參數(shù)傳進去一條消息。
        bgWorker.ReportProgress(i, message);
        Thread.Sleep(600);
    }
}

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

三、取消操作

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

 _demoBGWorker.WorkerSupportsCancellation = true;

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

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

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

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

四、異常處理

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

private void btnStart_Click(object sender, EventArgs e)
{
    _demoBGWorker.DoWork += BGWorker_DoWork;
    int num = int.Parse(numericUpDown1.Value.ToString());
    //給滾動條賦值
    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īng)結(jié)束,需要禁用取消按鈕。
    this.btnCancel.Enabled = false;
    //計算過程中的異常會被抓住,在這里可以進行處理。
    if (e.Error != null)
    {
        Type errorType = e.Error.GetType();
        switch (errorType.Name)
        {
            case "ArgumentNullExcepetion":
            case "MyException":
                //do something.
                break;
            default:
                //do something.
                break;
        }
    }
    //計算結(jié)果信息:e.Result
    //use it do something.
}

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

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

e.Result=sum;

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

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


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

主站蜘蛛池模板: 国内美女白浆视频久久网 | 7777精品伊人久久久大香线蕉 | 国产精品A久久久久久久久 国产精品JIZZ在线观看A片 | 日本无码人妻精品一区二区视频 | 成人a毛片高清视频 | 国产91精品一区二区三区四区高清在线观看 | 日韩aⅴ无码中文无码电影 日韩aⅴ亚洲欧美一区二区三区 | 欧美又爽又大又黄a片 | 国产成人a亚洲 | 在线免费观看国产视频 | 波多野结衣一区二区在线 | 久久免费国产精品一区二区 | 久久影院精品 | 无人区在线高清完整免费 | 动漫精品专区一区二区三区不 | 亚洲国产欧美一区二区欧美 | 国产清纯91天堂在线观看 | 日韩一区二区三区在线 | 丰满多毛少妇做爰视频 | 精品国产成人三级 | 国产av最新精品自在自线 | 国产精品精品国产 | 亚洲日韩国产成在线发布一区二区三区 | 国产传媒18精品A片在线观看 | 成人无码区免费视频观看 | 亚洲AV永久无码精品三区在线4 | 亚洲免费视频在线 | 欧美日韩在线观看一区二区三区 | 中文日产无乱码AV在线观 | 无AV在线中文字幕 | 亚洲欧美一区二区三区国产另类 | 久久久久久av无码免费网站下载 | 精品国产乱码久久久久久软件大全 | 色噜噜狠狠大色综合 | 国产人妻人伦又粗又大爽歪歪 | 女同蹭逼欧美视频 | 国精产品一二二区传媒有哪些 | 国产超薄肉丝袜在线播放 | 一区二区三区四区国产 | 久久国产伦三级理电影 | 91中文字幕 国产 高清 |