Maison  >  Article  >  développement back-end  >  Explication détaillée de l'utilisation de BackgroundWorker en C# (photo)

Explication détaillée de l'utilisation de BackgroundWorker en C# (photo)

黄舟
黄舟original
2017-04-13 09:58:112535parcourir

Cet article présente principalement l'explication détaillée de l'utilisation de C# BackgroundWorker. L'éditeur pense que c'est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un coup d'œil.

Dans les programmes C#, il y a souvent des opérations gourmandes en CPU qui prennent beaucoup de temps. Si de telles opérations sont effectuées directement sur le thread de l'interface utilisateur, le problème de non-réponse de l'interface utilisateur se posera. se produire. . Le principal moyen de résoudre ce type de problème consiste à utiliser le multithreading, à démarrer un thread en arrière-plan et à terminer les opérations informatiques dans ce thread en arrière-plan. Cependant, le fonctionnement des threads de l'interface native est quelque peu difficile. Si vous souhaitez compléter davantage la communication entre les threads, ce sera encore plus difficile.

Heureusement, la bibliothèque de classes .NET fournit une classe appelée BackgroundWorker qui peut résoudre ce genre de problème avec plus d'élégance. Bien que la classe BackgroundWorker soit relativement simple à utiliser, certains détails doivent encore être pris en compte. Ci-dessous, nous présenterons son utilisation principale via le programme de démonstration. Nous calculons la somme cumulée de 1 à 100 dans la démo. Pour démonstration, chaque calcul dort pendant 600 millisecondes. L'interface utilisateur de la démo est :

Aperçu de l'utilisation.

Créez une instance BackgroundWorker sur le formulaire, ajoutez des opérations fastidieuses à sa fonction de gestion des événements DoWork , puis appelez sa méthode 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;
  }
}

Ce n'est pas un peu trop simple ? Considérons donc la question suivante :

Et si on veut passer des paramètres à l'opération ?

Que devons-nous faire si nous voulons afficher des informations en temps réel sur l'interface utilisateur pendant le processus de calcul ?

Et si on souhaite annuler l'opération en cours ?

Que devons-nous faire si une exception survient pendant l'opération ?

Ensuite, nous traiterons ces problèmes un par un.

Transmettre des paramètres au processus de calcul

Il n'est pas bon d'écrire directement 100 dans le processus de calcul. Nous prévoyons également de permettre aux utilisateurs de spécifier la plage de la somme. ! Vous devez donc passer 100 comme paramètre au processus de calcul. Dans la présentation, nous démarrons le processus de calcul en appelant la méthode RunWorkerAsync. En fait, cette méthode peut accepter un paramètre de type d'objet. Grâce à lui, nous pouvons transmettre n'importe quelle donnée au processus de calcul :

//别忘了设置滚动条。
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;
  }
}

Le gestionnaire d'événements BGWorker_DoWork transmet les informations de calcul que nous attendons via l'attribut Argument du paramètre e.

Transférer le message vers l'interface utilisateur

Étant donné que le processus de calcul est relativement long, alors que nous affichons la progression actuelle via la barre de progression, nous j'espère également afficher les résultats intermédiaires du calcul sur l'interface utilisateur en temps réel. Bien entendu, BackgroundWorker fournit également un excellent support pour ce cas d’utilisation. Cela nous permet d'envoyer des messages au fil de discussion de l'interface utilisateur pendant le processus de calcul. Jetons un coup d'œil à la méthode spécifique :

_demoBGWorker.WorkerReportsProgress = true;
_demoBGWorker.ProgressChanged += BGWorker_ProgressChanged;

Tout d'abord, définissez la propriété WorkerReportsProgress sur true, puis. définir l'événement ProgressChanged Ajouter une méthode de traitement :

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

Continuer la mise à jour de la méthode 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);
  }
}

OK, vous pouvez maintenant voir la mise à jour de la barre de progression et des informations d'exécution.

Annuler l'opération

Permettre à l'utilisateur d'annuler l'opération en cours pendant l'exécution est une conception de base, et BackgroundWorker a naturellement un bon support :

_demoBGWorker.WorkerSupportsCancellation = true;

Identique à l'attribut WorkerReportsProgress, si nous voulons prendre en charge les opérations d'annulation, nous devons définir l'attribut WorkerSupportsCancellation sur true. Et vous devez également le prendre en charge dans la méthode BGWorker_DoWork, ajoutez du code après Thread.Sleep(600) dans la boucle for  :

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

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

Si le bouton Annuler cliqué par le l'utilisateur est détecté , il suffit de quitter le processus de calcul en cours. Voici le code à appeler lorsque vous cliquez sur le bouton Annuler :

_demoBGWorker.CancelAsync();

L'opération d'annulation est désormais prise en charge, essayez-la maintenant !

Gestion des exceptions

Que faire si une exception se produit lors du calcul ? Existe-t-il un moyen de savoir que le processus de calcul est terminé ? Bien sûr, même si cela se termine normalement, nous devons quand même obtenir les résultats calculés.

_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.
}

La fonction de gestionnaire d'événements RunWorkerCompleted sera appelée après le retour de la fonction de gestionnaire d'événements DoWork. Grâce à lui, nous pouvons effectuer certaines opérations après l'opération, comme la désactivation du bouton d'annulation, la gestion des exceptions, l'affichage des résultats, etc.

Notez que si vous souhaitez obtenir e.Result, vous devez définir l'attribut e.Result dans la méthode BGWorker_DoWork, tel que :

e.Result = sum;

En résumé, le La classe BackgroundWorker a des fonctions complètes et elle est facile à utiliser et constitue vraiment un outil puissant pour gérer les opérations asynchrones chronophages !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn