取消 BackgroundWorker 的正确方法

Proper way to cancel BackgroundWorker

这是我第一次使用 wpf。现有系统要处理一个excel文件,现在要求是,excel文件必须有5个comlumns。这是必须进行处理的代码

  void InsertIDsNamesAndAddWorker_DoWork(object sender, DoWorkEventArgs e)
            {
              // read the excel file here
                int columns = xlWorkSheet.UsedRange.Columns.Count;
                if (columns == 5)
                {
                    //do your normal processing
                }
                else
                {
                    //if requirements are not met then display error message
                    System.Windows.MessageBox.Show("There must be five columns in this 
                   file", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

现在这段代码确实进入了 else 部分,但是它继续到其他部分,然后显示一条错误消息 "done processing"。

这是执行确认消息的方法的当前代码

void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                ProgressBarValue = 100;
                StatusLable = "Done Processing.";
                if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
                {
                    StatusLable = string.Empty;
                    ProgressBarValue = 0;
                }
            }

现在我是 wpf 技术的新手,我意识到 Statuslable 的硬编码值是导致问题的原因,所以如果满足要求并完成处理,我将 ProgressBarValue 设置为 100 . 如果列数不等于 5,我还将 ProgressBarValue 设置为零。 这是新代码

void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                int count = ProgressBarValue;
                if (count != 100)
                {
                    StatusLable = string.Empty;
                    ProgressBarValue = 0;
                }
                else
                {
                    //ProgressBarValue = 100;
                    StatusLable = "Done Processing.";
                    if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
                    {
                        StatusLable = string.Empty;
                        ProgressBarValue = 0;
                    }
                }

            }

我的主要问题是,这是正确的方法吗?如果不符合要求,我还有什么其他方法可以取消工作吗?

BackgroundWorker 有一个名为 WorkerSupportsCancellation 的 属性。如果将其设置为 true,您将有另一个选项来取消执行。

每当发生错误时,您可以调用backgroundWorker.CancelAsync(),这会将布尔值设置为true(即BackgroundWorker对象中的CancellationPending 属性)。

然后您可以在执行期间检查 CancellationPending 是否为真。如果是这样,工人应该停下来。

如果 worker 停止,它将启动 RunWorkerCompleted 事件,该事件将在方法的处理程序中结束(如果添加的话)。

这种取消方式可以在所有指令中检查,或者在 for 循环的开始处检查(如:for (int i = 0; (i < x) && worker.CancellationPending; i++) ;

希望对您有所帮助!

使用您在 DoWork 中传递的 DoWorkEventArgs 实例的 Result 属性:

void InsertIDsNamesAndAddWorker_DoWork(object sender, DoWorkEventArgs e)
{
    if (columns == 5)
    {
        //do your normal processing
        e.Result = true; // we're OK
    }
    else
    {
        //if requirements are not met then display error message
        System.Windows.MessageBox.Show("There must be five columns in this 
       file", MessageBoxButton.OK, MessageBoxImage.Error);

       e.Result = false; // something wrong
    }
}

然后在 RunWorkerCompleted 中检查 Result 值并进行相应处理。

void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // check if we're not cancelled or error-ed before checking the Result
    result = (!e.Cancelled && e.Error == null)? (bool) e.Result: false; // what is the outcome

    ProgressBarValue = 100;
    if (result) {
        StatusLable = "Done Processing.";
        if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
        {
            StatusLable = string.Empty;
            ProgressBarValue = 0;
        }
    } 
    else 
    {
         StatusLable = "Error in Excel sheet";
    }
}

注意 Result 是对象类型。您可以将任何类型的实例放入其中,甚至是您自己的 class,如果您想要 return 关于出错原因的更详细的细节,可能需要它。