2012-08-22 3 views
0

J'ai une bonne compréhension de la façon d'utiliser le System.ComponentModel.BackgroundWorker, fondamentalement, vous avez une seule fonction "DoWork" et généralement une boucle qui fonctionne et à chaque itération, vous vérifiez e.Cancel pour déterminer si oui ou non et arrêtez la boucle pour mettre fin au "DoWork" de BackgroundWorker (ceci suppose que la propriété WorkerSupportsCancellation est définie correctement sur true). Ce dont je ne suis pas sûr, c'est que si j'ai une fonction récursive (la fonction exacte n'a pas d'importance, une fonction récursive disons les factoriels de calcul classiques) qui effectue ma tâche (plutôt qu'une boucle) comment puis-je appelez cela à partir d'une fonction "DoWork", et comment puis-je propager le e.Cancel dans ce cas pour renflouer sur la récursivité?BackgroundWorker avec une fonction récursive

+0

http://whathaveyoutried.com? Tu ne peux pas utiliser le mot-clé 'ref'? –

Répondre

3

Voulez-vous dire quelque chose comme ça? Dès que l'annulation est lancée, la boucle récursive se déroule jusqu'au sommet et vous êtes arrêté.

void RecursiveLoop(BackGroundWorker worker) 
{ 
    // ON entry check if we need to stop 
    if (worker.CancellationPending) return; 
    // 
    // Normal code and the recursion 
    if (morework) RecursiveLoop(worker); 
} 
+0

Cool merci, en passant le 'BackGroundWorker' est certainement un moyen rapide de le faire, esp. si je veux aussi signaler un certain type de progrès dans la récursivité. Cependant, n'est-ce pas sûr qu'Erno peut être plus efficace? – user17753

+0

Vous ne savez pas pourquoi vous utiliseriez l'itinéraire délégué. Comme vous passez les délégués tout comme le bgworker, je ne vois pas plus d'efficacité. – IvoTops

+0

Je pense que cette réponse me semble la plus logique. – user17753

2

Créez un délégué à la fonction qui annule le travail d'arrière-plan.

Créez un délégué à la fonction qui renvoie la valeur false lorsque l'annulation du travail d'arrière-plan est en attente.

Passez ces délégués à la fonction récursive et assurez-vous qu'il transmet ces délégués à chaque appel récursif.

Dans la fonction récursive, appelez le premier délégué lorsque vous souhaitez annuler le travail d'arrière-plan.

Enfin, dans la fonction récursive, recherchez une annulation en attente en utilisant le second délégué. De cette façon, vous n'avez pas besoin de passer le travailleur d'arrière-plan par-dessus.

0

Vérifiez e.Cancel au début de la fonction et, s'il est vrai, définir une variable membre dans le cadre de la classe. Utilisez cette variable pour déterminer s'il faut continuer ou non.

1

Avez-vous envisagé d'écrire une boucle récursive déroulée? Les avantages d'un « déroulé boucle recusive » sont:

  • La pile <> L'objet peut utiliser toute la mémoire disponible, mais ne sera pas entraîner une stackoverflow
  • L'appel de fonction peut être annulée avec un test et retour, peu importe la profondeur de la file d'attente était
  • vous pouvez rapporter des progrès à ce sujet, si vous le souhaitez (par exemple, pourcentage progress = num_items_processed/taille de la pile + num_items_processed)
  • vous pouvez mettre en pause le moment de l'exécution que vous voulez et le reprendre plus tard

Voici une éventuelle mise en œuvre d'une récursion déroula:

void RecursiveLoop(WorkItem item) 
{ 
    // Create a stack and push our item onto it 
    Stack<WorkItem> recursion = new Stack<WorkItem>(); 
    recursion.Push(item); 

    // Loop through all items in the stack 
    while ((!cancel_flag_set) && (recursion.Count > 0)) { 
     WorkItem current = recursion.Pop(); 

     // ... Do Work Here ... 

     // Now, queue up all the child items 
     foreach (WorkItem child in current.ChildItems) { 
      recursion.Push(child); 
     } 
    } 
} 
+0

+1 De bonnes choses Ted. – user17753

Questions connexes