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

.net 取消e.result中的后台工作程序异常,.net,backgroundworker,.net,Backgroundworker,我和背景工作者有严重的问题。如果任务结束,则代码正常工作。当我取消后台任务时,在e.Result的RunWorkerCompleted函数中会出现system.invalidoperationexception。怎么了?多谢各位 这是我的cod: private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { if (backgroundWorker.CancellationPending == true)

我和背景工作者有严重的问题。如果任务结束,则代码正常工作。当我取消后台任务时,在e.Result的RunWorkerCompleted函数中会出现system.invalidoperationexception。怎么了?多谢各位

这是我的cod:

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;
} 
private void backgroundWorker\u DoWork(对象发送方,DoWorkEventArgs e)
{
if(backgroundWorker.CancellationPending==true)
e、 取消=真;
e、 结果=结果列表;
}
私有void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
如果(例如错误!=null)
List resultList=(List)e.Result;
} 

这是根据设计,当DoWork被取消或抛出异常时,结果属性getter将抛出。只需检查一下:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (!e.Cancelled && e.Error == null) {
       List<Object> resultList = (List<Object>)e.Result;
       // etc..
    }
} 
private void backgroundWorker1\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
如果(!e.Cancelled&&e.Error==null){
List resultList=(List)e.Result;
//等等。。
}
} 
经过长期的努力(作为新手),我成功地将@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;

                        }
                }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用系统组件模型;
使用系统数据;
命名空间取消BackgroundWorker
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
私有BackgroundWorker worker=null;
公共主窗口()
{
初始化组件();
worker=新的BackgroundWorker();
worker.worker支持扫描单元=true;
worker.WorkerReportsProgress=true;
worker.DoWork+=worker\u DoWork;
worker.ProgressChanged+=worker\u ProgressChanged;
worker.RunWorkerCompleted+=worker\u RunWorkerCompleted;
}
私有void btnStart\u单击(对象发送方,路由目标)
{
worker.RunWorkerAsync();
}
私有void btnCancel\u单击(对象发送者、路由目标)
{
worker.CancelAsync();
}
无效工作线程(对象发送器,工作线程目标)
{

对于(int i=0;i而不是将e.Cancel设置为true(这会导致异常),您可以在DoWork事件中将类设置为e.Result,该事件包含您的结果和一个指示任务是否完成的变量。或者,如果您的c#是最新的,您可以简单地将其设置为元组

…在嫁妆中

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!");

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

ah ok,但是如果取消,我需要结果事件,该怎么办?仔细想想:如果DoWork被取消或被异常中断,那么您就无法得到有效的结果。它没有完成。它被故意取消:用户可以中止耗时的任务k、 然后调用backgroundWorker.CancelAsync(),还没有异常。我想向用户显示到目前为止的结果。如何做到这一点,我没有任何结论。如果不将e.Cancel属性设置为true,只需分配e.result并退出即可。使用CancelAsync()将backgroundWorker.CancellationPending设置为true。不要将e.Cancel设置为true.Simple。