我对后台工作者有严重问题。如果任务正常结束,代码正在工作。当我取消后台任务时,我在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;
}
答案 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!");
这当然是假设您想知道任务是否完成。