欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

C#中的BackgroundWorker詳解

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

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

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

用法概述:

在窗體上構建一個BackgroundWorker實例,在它的DoWork事件處理函數中添加耗時的運算,然后調用它的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      //在這里執行耗時運算。
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  }

以上部分,暫時沒有加入進度條的顯示邏輯,以及其余耗時的計算,但我們可以先考慮下面幾個問題:

  • 如果我們要想把參數傳遞給運算過程怎么做?
  • 在運算過程中我們希望把實時的信息顯示在UI上應該怎么辦?
  • 如果我們想要取消正在進行的運算該怎么辦?
  • 如果運算過程出現異常我們又該如何處理?

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

一、把參數傳遞給運算過程:

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

        private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //在這里執行耗時運算。
            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事件處理函數通過參數e的Argument屬性傳來了我們期望的運算信息。

二、把消息傳遞給UI

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

 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屬性設置為true,然后為ProgressChanged事件添加處理方法:

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

繼續更新BGWorker_DoWork方法:

private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bgWorker=sender as BackgroundWorker;
    //在這里執行耗時運算。
    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事件處理函數。
        //第一個參數類型為 int,表示執行進度。
        //如果有更多的信息需要傳遞,可以使用ReportProgress的第二個參數。
        //這里我們給第二個參數傳進去一條消息。
        bgWorker.ReportProgress(i, message);
        Thread.Sleep(600);
    }
}

現在,我們已經可以看到進度條和執行信息的更新了。

三、取消操作

  在執行過程中允許用戶取消當前的操作是一個基本的設計,BackgroundWorker自然有很好的支持:

 _demoBGWorker.WorkerSupportsCancellation = true;

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

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

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

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

四、異常處理

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

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)
{
    //如果用戶取消了當前操作就關閉窗口。
    if (e.Cancelled)
    {
        this.Close();
    }
    //計算已經結束,需要禁用取消按鈕。
    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;
        }
    }
    //計算結果信息:e.Result
    //use it do something.
}

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

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

e.Result=sum;

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

轉自https://www.cnblogs.com/Sheldon180621/p/18245692


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