J'ai un grave problème avec le travailleur de fond. Le code fonctionne si la tâche se termine régulièrement. Lorsque j'annule la tâche d'arrière-plan, je reçois un système.InvalidoperationException dans la fonction d'exécution exécutée pour E.Result. Qu'est-ce qui ne va pas? Merci.
Voici ma morue: p>
3 Réponses :
Ceci est par conception, le résultat de la propriété Getter lancera lorsque Dowork a été annulé ou jeté une exception. Vérifiez simplement que:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!e.Cancelled && e.Error == null) { List<Object> resultList = (List<Object>)e.Result; // etc.. } }
Ah Ok, mais que faire si j'ai besoin d'événement de résultat si annulé?
Pensez à cela un peu: si Dowork a été annulé ou interrompu par une exception, vous ne pouvez pas avoir de résultat valide. Cela n'a pas été fait.
Il est annulé par intention: l'utilisateur peut annuler une tâche fastidieuse de temps, puis appellé le Backworker.Cancelasync () est appelé, pas encore d'exception. Je veux présenter l'utilisateur le résultat jusqu'à présent. Comment puis-je faire cela, je n'ai aucune idée
Ensuite, ne définissez pas la propriété E.cancel sur true, il suffit d'attribuer à E.Result et de sortie.
Ensuite, comment signaler le fil pour s'arrêter au lieu d'utiliser AnnuynASync ()?
Utilisez AnnuensaSync () pour obtenir des backgroundsworker.CancellationPender défini sur true. Ne définissez pas E.cancel à vrai. Simple.
Après une longue lutte (être novice), j'ai réussi à incorporer la suggestion de @ Hans avec mon code. J'espère que le bloc de code suivant aide les débutants comme moi qui souhaitent renvoyer les résultats actuellement traités lorsque AnnyclASync () est appelé.
Bloc de code P>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel; using System.Data; namespace CancelBackgroundWorker { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private BackgroundWorker worker = null; public MainWindow() { InitializeComponent(); worker = new BackgroundWorker(); worker.WorkerSupportsCancellation = true; worker.WorkerReportsProgress = true; worker.DoWork += worker_DoWork; worker.ProgressChanged += worker_ProgressChanged; worker.RunWorkerCompleted += worker_RunWorkerCompleted; } private void btnStart_Click(object sender, RoutedEventArgs e) { worker.RunWorkerAsync(); } private void btnCancel_Click(object sender, RoutedEventArgs e) { worker.CancelAsync(); } void worker_DoWork(object sender, DoWorkEventArgs e) { for(int i = 0; i <= 100; i++) { if(worker.CancellationPending == true) { //http://stackoverflow.com/questions/8300799/cancel-background-worker-exception-in-e-result // e.Cancel = true; //This does the trick e.Result = 100; return; } worker.ReportProgress(i); System.Threading.Thread.Sleep(250); } e.Result = 42; } void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { lblStatus.Text = "Working... (" + e.ProgressPercentage + "%)"; } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if(e.Cancelled) { lblStatus.Foreground = Brushes.Red; lblStatus.Text = "Cancelled by user..." + e.Result; } else { lblStatus.Foreground = Brushes.Green; lblStatus.Text = "Done... Calc result: " +e.Result; } } } }
au lieu de régler E.cancel à true (qui provoque l'exception), vous pouvez définir une classe à E.Result dans l'événement Dowork contenant à la fois votre résultat et une variable indiquant si la tâche a été complétée ou non. Ou si votre C # est à jour, vous pouvez simplement la définir comme un tuple ...
... dans Dowork ... P>
var (completed, resultList) = (bool, WhateverListTypeYouUsed)e.Result; if(completed) Debug.WriteLine("Hooray!");