2009-09-24 5 views
1
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace ClassLibrary 
{ 
    public class MyClass 
    { 
     public static string LongOperation() 
     { 
      Thread.Sleep(new TimeSpan(0,0,30)); 

      return "HelloWorld"; 
     } 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

using ClassLibrary; 

namespace BackgroungWorker__HelloWorld 
{ 
    public partial class MainForm : Form 
    { 
     public MainForm() 
     { 
      InitializeComponent(); 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      if (backgroundWorker1.CancellationPending) 
      { 
       e.Cancel = true; 
       return; 
      } 

      MyClass.LongOperation(); 

      e.Result = "[Result]"; 
     } 

     private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     {    
     } 

     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      try 
      { 
       if (e.Cancelled) 
       { 
        MessageBox.Show("The task has been cancelled"); 
       } 
       else if (e.Error != null) 
       { 
        MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString()); 
       } 
       else 
       { 
        MessageBox.Show("The task has been completed. Results: " + e.Result!=null?e.Result.ToString():" null"); 
       } 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 

     private void btnStart_Click(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 

     private void btnClose_Click(object sender, EventArgs e) 
     { 
      if (backgroundWorker1.IsBusy) 
      { 
       backgroundWorker1.CancelAsync(); 
      } 
      else 
      { 
       this.Close(); 
      } 
     } 
    } 
} 

Je trouve que, après l'exécution du code suivant:C# BackgroundWorker Discussion Problème

private void btnClose_Click(object sender, EventArgs e) 
     { 
      if (backgroundWorker1.IsBusy) 
      { 
       backgroundWorker1.CancelAsync(); 
      } 
      else 
      { 
       this.Close();//"this" means the Form object 
      } 
     } 

fil de la backgroundWorker1 n'est pas tué immédiatement. Cela prend du temps.

Cela a été un problème dans la construction de ma logique d'application.

Quelqu'un peut-il m'aider à cet égard?

+0

En fait, il s'agit d'une simulation d'une application DB, où MyClass.LogOperation() simule une opération d'extraction longue. – anonymous

+0

+1 Je voudrais également une solution pour annuler les opérations asynchrones de longue durée (c'est-à-dire appel DB). Je vais regarder ... :) – Pwninstein

Répondre

4

La solution est de changer votre gestionnaire d'événements de l » DoWork() de BackgroundThread être plus réactif: il a besoin pour briser son travail en petits morceaux et sondage CancellationPending du travailleur assez souvent pour satisfaire les besoins de votre application.


Modifier: étant donné le code que vous avez ajouté, vous ne serez pas en mesure de faire ce que vous voulez avec BackgroudWorker. Si vous ne pouvez pas modifier MyClass.LongOperation (et qu'il ne fournit aucun hook pour vous permettre de l'interrompre) mais que vous voulez laisser l'utilisateur annuler avant la fin de cette opération, vous pouvez implémenter ceci en créant votre propre Thread (comme arrière-plan thread, qui ne gardera pas votre application ouverte si vous l'abandonnez). Théoriquement, vous pouvez également le faire en utilisant ThreadPool.QueueUserWorkItem, sauf que c'est une mauvaise idée d'utiliser le ThreadPool pour les processus de longue durée (voir The Managed Thread Pool pour plus de détails). Enfin, vous pouvez envisager de déplacer l'opération de longue durée hors bande - écrire un message dans une file d'attente, appeler un service ou utiliser une autre technique pour la transférer à un autre processus.

+0

+1. Dang, 4 réponses identiques tous dans la minute. Je viens de supprimer le mien. –

+0

Cela n'est pas possible si je dois conserver mes couches logiques inférieures intactes. Un autre moyen? – anonymous

+0

@JMSA - pas aussi loin que je sache. Il y a plusieurs questions similaires sur SO (par exemple, http://stackoverflow.com/questions/543811/kill-the-thread-of-backgroundworker). Le résultat est que vous devez utiliser un mécanisme différent de BackgroundWorker si vous prévoyez d'abandonner vos threads. –

1

Cela dépend de la fréquence à laquelle votre méthode DoWork() vérifie la propriété CancellationPending.

C'est une demande d'annulation, vous ne tuez pas le fil. Reportez-vous à la page msdn sur CancelAsync

Il n'existe aucun moyen réel de mettre fin à BackgroundWorker, utilisez plutôt un thread.

1

Il appartient au code workerthreads de vérifier la propriété CancellationPending. Le code exécuté entre ces vérifications sera toujours exécuté, ce qui provoque un retard.

Dans votre remarque, vous avez une belle apparence. Une solution consiste à créer une sous-classe spécifique pour le multi-threading, afin de laisser les bits indésirables inévitables hors de la logique. La classe principale doit fournir une méthode template pour LongOperation qui appelle d'autres méthodes, la sous-classe threading peut alors remplacer les méthodes appelées longoperation, et avant de laisser les méthodes mainclass faire le travail réel effectuer la vérification de la propriété CancellationPending. De cette façon, vous pouvez arrêter plus arbitrairement qu'à la fin de la longue opération.

multithreading d'une manière non fonctionnelle toujours affecter votre code, tenez quand vous serez serrures besoin ;-)

0

Pouvez-vous décrire ce que la question est? Sûrement il est préférable de laisser gracieusement terminer le travail de l'arrière-plan (comme il le fait par conception).

Vous êtes conscient que vous pouvez vérifier périodiquement une annulation en effectuant backgroundWorker1. CancellationPending?

Questions connexes