Rumah pembangunan bahagian belakang Tutorial C#.Net C#中BackgroundWorker用法的详解(图)

C#中BackgroundWorker用法的详解(图)

Apr 13, 2017 am 09:58 AM

本篇文章主要介绍了C# BackgroundWorker使用详解 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

在C#程序中,经常会有一些耗时较长的CPU密集型运算,如果直接在 UI 线程执行这样的运算就会出现UI不响应的问题。解决这类问题的主要途径是使用多线程,启动一个后台线程,把运算操作放在这个后台线程中完成。但是原生接口的线程操作有一些难度,如果要更进一步的去完成线程间的通信就会难上加难。

还好 .NET 类库中提供了一个叫做 BackgroundWorker 的类可以比较优雅的解决这类问题。虽然BackgroundWorker 类使用起来比较简单,但其中还是有一些需要注意的细节,下面我们就通过 demo 程序介绍它的主要用法。我们在 demo中计算1到100的累加和,为了演示,每次计算都 sleep 600毫秒,demo 的UI为:

用法概述

在窗体上构建一个BackgroundWorker 实例,在它的 DoWork事件处理函数中添加耗时的运算,然后调用它的RunWorkerAsync方法就可以了。

private BackgroundWorker _demoBGWorker = new BackgroundWorker();
_demoBGWorker.DoWork += BGWorker_DoWork;
_demoBGWorker.RunWorkerAsync();
private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
{
  //在这里执行耗时的运算。
  int sum = 0;
  for (int i = 0; i <= 100; i++)
  {
    sum += i;
  }
}
Salin selepas log masuk

是不是有点太简单了?那么让我们考虑下面的问题:

如果我们想要把参数传递给运算过程该怎么做?

在运算过程中我们希望把实时的信息显示在UI上该怎么办?

如果我们想要取消正在进行的运算该怎么办?

如果运算过程出现异常我们又该如何处理?

接下来我们就一个一个的处理这些问题。

把参数传递给运算过程

直接把100写死到运算过程中可不好,我们还打算允许用户指定求和的范围呢!所以需要把100作为参数传递给计算过程。在概述中我们通过调用RunWorkerAsync方法启动计算过程,其实这个方法可以接受一个 object 类型的参数。通过它我们就可以把任何数据传递给计算过程:

//别忘了设置滚动条。
this.progressBarSum.Maximum = 100;
_demoBGWorker.RunWorkerAsync(100);
//下面是更新后的 BGWorker_DoWork 方法:
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;
  }
}
Salin selepas log masuk

BGWorker_DoWork事件处理函数通过参数 e 的Argument属性传来了我们期望的运算信息。

把消息传递给UI

由于计算过程比较长,我们在通过进度条来显示当前进度的同时,还希望能实时的把计算的中间结果显示在UI上。当然,BackgroundWorker对这个用例也提供了很好的支持。它允许我们在执行计算的过程中给UI线程发送消息,下面看看具体的做法:

_demoBGWorker.WorkerReportsProgress = true;
_demoBGWorker.ProgressChanged += BGWorker_ProgressChanged;
Salin selepas log masuk

首先要把WorkerReportsProgress 属性设置为 true,然后为ProgressChanged 事件添加处理方法:

private void BGWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
  //修改进度条的显示。
  this.progressBarSum.Value = e.ProgressPercentage;

  //如果有更多的信息需要传递,可以使用 e.UserState 传递一个自定义的类型。
  //这是一个 object 类型的对象,您可以通过它传递任何类型。
  //我们仅把当前 sum 的值通过 e.UserState 传回,并通过显示在窗口上。
  string message = e.UserState.ToString();
  this.labelSum.Text = message;
}
Salin selepas log masuk

继续更新 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.ToString();
    //ReportProgress 方法把信息传递给 ProcessChanged 事件处理函数。
    //第一个参数类型为 int,表示执行进度。
    //如果有更多的信息需要传递,可以使用 ReportProgress 的第二个参数。
    //这里我们给第二个参数传进去一条消息。
    bgWorker.ReportProgress(i, message);
    Thread.Sleep(600);
  }
}
Salin selepas log masuk

OK,现在已经可以看到进度条和执行信息的更新了。

取消操作

在执行过程中允许用户取消当前的操作是一个基本的设计,BackgroundWorker自然有很好的支持:

_demoBGWorker.WorkerSupportsCancellation = true;
Salin selepas log masuk

和WorkerReportsProgress属性一样,如果要支持取消操作我们需要设置 WorkerSupportsCancellation属性为 true。并且还要在BGWorker_DoWork方法中进行支持,在 for 循环中 Thread.Sleep(600)后面添加代码:

 bgWorker.ReportProgress(i, message);
Thread.Sleep(600);

//在操作的过程中需要检查用户是否取消了当前的操作。
if (bgWorker.CancellationPending == true)
{
  e.Cancel = true;
  break;
}
Salin selepas log masuk

如果检测到用户点击的取消按钮,就退出当前的计算过程。下面是点击取消按钮时要调用的代码:

_demoBGWorker.CancelAsync();
Salin selepas log masuk

现在已经可以支持取消操作了,赶快试试吧!

异常处理

如果在计算过程中发生了异常该怎么处理?有没有办法知道计算过程已经结束?当然要有,即便是正常的结束也需要拿到计算的结果。

_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 "ArgumentNullException":
      case "MyException":
        //do something.
        break;
      default:
        //do something.
        break;
    }
  }

  //计算结果信息:e.Result
  //use it do something.
}
Salin selepas log masuk

RunWorkerCompleted 事件处理函数会在DoWork 事件处理函数返回后被调用。通过它我们可以进行一些运算结束后的操作,比如禁用取消按钮,异常处理,结果显示等。

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

e.Result = sum;
Salin selepas log masuk

总结,BackgroundWorker 类功能完善且使用简便,实在是处理异步耗时操作的利器!

Atas ialah kandungan terperinci C#中BackgroundWorker用法的详解(图). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Direktori Aktif dengan C# Direktori Aktif dengan C# Sep 03, 2024 pm 03:33 PM

Panduan untuk Active Directory dengan C#. Di sini kita membincangkan pengenalan dan cara Active Directory berfungsi dalam C# bersama-sama dengan sintaks dan contoh.

Penjana Nombor Rawak dalam C# Penjana Nombor Rawak dalam C# Sep 03, 2024 pm 03:34 PM

Panduan untuk Penjana Nombor Rawak dalam C#. Di sini kita membincangkan cara Penjana Nombor Rawak berfungsi, konsep nombor pseudo-rawak dan selamat.

Paparan Grid Data C# Paparan Grid Data C# Sep 03, 2024 pm 03:32 PM

Panduan untuk Paparan Grid Data C#. Di sini kita membincangkan contoh cara paparan grid data boleh dimuatkan dan dieksport daripada pangkalan data SQL atau fail excel.

C# Serialisasi C# Serialisasi Sep 03, 2024 pm 03:30 PM

Panduan untuk Pensirian C#. Di sini kita membincangkan pengenalan, langkah-langkah objek siri C#, kerja, dan contoh masing-masing.

Akses Pengubahsuai dalam C# Akses Pengubahsuai dalam C# Sep 03, 2024 pm 03:24 PM

Panduan kepada Pengubahsuai Akses dalam C#. Kami telah membincangkan Pengenalan Jenis Pengubahsuai Akses dalam C# bersama-sama dengan contoh dan output.

Corak dalam C# Corak dalam C# Sep 03, 2024 pm 03:33 PM

Panduan kepada Corak dalam C#. Di sini kita membincangkan pengenalan dan 3 jenis Corak teratas dalam C# bersama-sama dengan contoh dan pelaksanaan kodnya.

Nombor Perdana dalam C# Nombor Perdana dalam C# Sep 03, 2024 pm 03:35 PM

Panduan Nombor Perdana dalam C#. Di sini kita membincangkan pengenalan dan contoh nombor perdana dalam c# bersama dengan pelaksanaan kod.

Faktorial dalam C# Faktorial dalam C# Sep 03, 2024 pm 03:34 PM

Panduan untuk Faktorial dalam C#. Di sini kita membincangkan pengenalan kepada faktorial dalam c# bersama-sama dengan contoh dan pelaksanaan kod yang berbeza.

See all articles