取消e.result中的后台工作程序异常

时间:2011-11-28 18:55:35

标签: .net backgroundworker

我对后台工作者有严重问题。如果任务正常结束,代码正在工作。当我取消后台任务时,我在e.Result的RunWorkerCompleted函数中得到一个system.invalidoperationexception。怎么了?谢谢。

这是我的鳕鱼:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
  if (backgroundWorker.CancellationPending == true)
    e.Cancel = true;
  e.Result = resultList;
}


private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  if (e.Error != null)
    List<Object> resultList = (List<Object>)e.Result;
} 

3 个答案:

答案 0 :(得分:6)

这是设计的,当DoWork被取消或引发异常时,Result属性getter将抛出。只需检查一下:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (!e.Cancelled && e.Error == null) {
       List<Object> resultList = (List<Object>)e.Result;
       // etc..
    }
} 

答案 1 :(得分:0)

经过长时间的努力(作为一个新手),我设法将@Hans的建议与我的代码结合起来。希望以下代码块可以帮助像我这样的初学者在调用cancelasync()时想要返回当前处理的结果。

代码块

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;

                        }
                }

    }
}

答案 2 :(得分:0)

您可以将DoWork事件中的e.Result设置为e.Result,而不是将e.Cancel设置为true(这会导致异常),该类同时包含您的结果和指示任务是否完成的变量。或者,如果您的C#是最新的,则可以将其设置为元组...

...在DoWork中...

while(doingWork) {
   if(worker.CancellationPending) {
      e.Result = (false, resultList);
      return;
   }
   resultList.Add(someResult);
}
e.Result = (true, resultList);

...在RunWorkerCompleted中...

var (completed, resultList) = (bool, WhateverListTypeYouUsed)e.Result;
if(completed) Debug.WriteLine("Hooray!");

这当然是假设您想知道任务是否完成。