ホームページ  >  記事  >  バックエンド開発  >  C#でのBackgroundWorkerの使い方を詳しく解説(画像)

C#でのBackgroundWorkerの使い方を詳しく解説(画像)

黄舟
黄舟オリジナル
2017-04-13 09:58:112515ブラウズ

この記事では主に C#BackgroundWorker の使い方を詳しく紹介していますので、参考になれば幸いです。エディターに従って見てみましょう

C# プログラムでは、CPU に負荷がかかり、長時間かかる操作が UI スレッド上で直接実行されると、UI が応答しなくなるという問題が発生することがあります。この種の問題を解決する主な方法は、マルチスレッドを使用し、バックグラウンド スレッドを開始し、このバックグラウンド スレッドでコンピューティング操作を完了することです。ただし、ネイティブ インターフェイスのスレッド操作は少し難しく、スレッド間の通信をさらに完了させたい場合はさらに難しくなります。

幸いなことに、.NET クラス ライブラリ は、この種の問題をよりエレガントに解決できる BackgroundWorker と呼ばれるクラスを提供します。 BackgroundWorker クラスは比較的簡単に使用できますが、注意が必要な詳細がいくつかあります。以下では、デモ プログラムを通じてその主な使用方法を紹介します。デモでは、1 から 100 までの累積合計を計算します。デモでは、各計算は 600 ミリ秒間スリープします。 デモの UI は次のとおりです。時間のかかる操作を DoWork

イベント処理

関数

に追加し、その RunWorkerAsync メソッドを呼び出すだけです。

rreeちょっとシンプルすぎませんか?それでは、次の質問について考えてみましょう:

操作プロセスにパラメータを渡したい場合はどうすればよいでしょうか?

計算プロセス中にリアルタイムの情報を UI に表示したい場合はどうすればよいですか?

進行中の操作をキャンセルしたい場合はどうすればよいですか?

操作中に例外が発生した場合はどうすればよいですか?

次に、これらの問題を 1 つずつ解決していきます。


計算プロセスにパラメータを渡す


計算プロセスに直接100を書き込むのは良くありません。また、合計の範囲をユーザーが指定できるようにする予定です。したがって、計算プロセスにパラメータとして 100 を渡す必要があります。概要では、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;
  }
}

BGWorker_DoWork イベント処理関数は、パラメーター e の引数

属性

を介して、期待される計算情報を渡します。

UI にメッセージを渡します

計算プロセスは比較的長いため、現在の進行状況を

プログレスバーで表示しながら、計算の中間結果もリアルタイムで UI に表示したいと考えています。もちろん、BackgroundWorker はこのユースケースにも優れたサポートを提供します。これにより、計算の実行中に UI スレッド

にメッセージを送信できるようになります。具体的なメソッドを見てみましょう:

//别忘了设置滚动条。
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;
  }
}
まず、WorkerReportsProgress プロパティを true に設定し、次に ProgressChanged イベントの処理メソッドを追加します:
_demoBGWorker.WorkerReportsProgress = true;
_demoBGWorker.ProgressChanged += BGWorker_ProgressChanged;

BGWorker_DoWork メソッドの更新を続けます:

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;
}
OK、これで、進行状況バーと実行情報の更新が表示されます。 操作のキャンセル

ユーザーが実行中に現在の操作をキャンセルできるようにすることは基本的な設計であり、BackgroundWorker には当然優れたサポートがあります:

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);
  }
}

WorkerReportsProgress 属性と同様に、キャンセル操作をサポートしたい場合は、 WorkerSupportsCancel 属性は true です。また、BGWorker_DoWork メソッドでもこれをサポートする必要があり、for

ループ

の Thread.Sleep(600) の後にコードを追加します:

_demoBGWorker.WorkerSupportsCancellation = true;
ユーザーがクリックしたキャンセル ボタン

が検出された場合、

現在の計算プロセスを

終了します。 。以下は、キャンセル ボタンをクリックしたときに呼び出されるコードです:

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

//在操作的过程中需要检查用户是否取消了当前的操作。
if (bgWorker.CancellationPending == true)
{
  e.Cancel = true;
  break;
}
キャンセル操作がサポートされるようになりました。今すぐお試しください。

例外処理

計算中に例外が発生した場合はどうすればよいですか?計算プロセスが終了したことを知る方法はありますか?もちろん、正常に終了したとしても、計算結果を取得する必要があります。

_demoBGWorker.CancelAsync();

RunWorkerCompleted イベント ハンドラー関数は、DoWork イベント ハンドラー関数が返された後に呼び出されます。これにより、キャンセルボタンの無効化、例外処理、結果表示など、操作後にいくつかの操作を実行できます。

e.Result を取得したい場合は、BGWorker_DoWork メソッドで次のように e.Result 属性を設定する必要があることに注意してください。

_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.
}
要約すると、BackgroundWorker クラスは完全な機能を備えており、使いやすいです。は、時間のかかる非同期操作を処理するための非常に強力なツールです。

以上がC#でのBackgroundWorkerの使い方を詳しく解説(画像)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。