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

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

主站蜘蛛池模板: 99热免费观看 | 日韩在线视频www色 日韩在线视频观看在线看 日韩在线一 | 久久频这里精品99香蕉久网址 | 免费麻花豆传媒剧国产MV | 国产av综合a∨一区二区三区 | 国产私密网站入口 | 精品国产日韩亚洲一区尤物 | 国产一区二区精品在线观看 | 果冻传媒九一制片厂电影女频恋爱 | 久久久久无码精品国产91福利 | 久久国产精品只做精品 | 玖玖爱视频在线观看 | 亚洲av极品在线观看 | a级在线中文字幕在线 | av撸色| 精品国产免费一区二区三区五区 | 国产乱伦在线播放 | av无码乱码在线观看性色 | 国产亚洲精品久久久久久国 | 日韩精品一区在线观看 | 国产片MV在线观看 | 人妻少妇乱 | 无码av熟妇素人内射v在线 | 东京一本大道无码 | 国产99在线亚洲 | 2024日本三级电影免费在线播放 | 国精产品一二二区视频 | a级无遮挡超级高清一在线观看 | 天天综合久久久网 | 日本小视频天堂久久 | XXX欧美性兽交 | 精品久久久国产中文 | 欧美日韩一区二区三区久久精品 | 六月色香婷婷一区二区三区 | 亚洲国产成人高清在线观看 | 国产精品日韩欧美久久综合 | 日本免费一区二区三区四区五六区 | 永久免费aⅴ无码网站在线观看 | 被少妇滋润了一夜爽爽爽小说 | 午夜污污污一区二区三区 | 日韩精品在线免费观看 |