简体   繁体   English

取消BackgroundWorker的正确方法

[英]Proper way to cancel BackgroundWorker

Its my first time working on a wpf. 这是我第一次使用wpf。 An existing system has to process an excel file, now the requirement is, the excel file must have five comlumns. 现有系统必须处理excel文件,现在的要求是,excel文件必须有五个逗号。 Here is the code that has to do the processing 这是要做处理的代码

  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);
                }
            }

Now this code does get into the else part, it however continues to other part which then displays an error message that says "done processing". 现在,此代码确实进入了其他部分,但是继续到其他部分,然后显示一条错误消息,指出“处理完成”。

Here is the current code of the method that does the confirmation message 这是执行确认消息的方法的当前代码

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;
                }
            }

Now with me being new to the wpf technology, I realized that the hard-coded value of Statuslable is the one causing issues, so I went to set the ProgressBarValue to 100 if the the requirements were met and processing is done. 现在,我是wpf技术的新手,我意识到Statuslable的硬编码值是引起问题的一个原因,因此,如果满足要求并已完成处理,则我将ProgressBarValue设置为100。 I also set the ProgressBarValue to zero if the colums was not equal to 5. Here is the new code 如果列不等于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;
                    }
                }

            }

My main question is, is this the right way though? 我的主要问题是,这是否正确? is the any other way I can cancel the work if requirements are not met? 如果不满足要求,我还有其他方法可以取消工作吗?

The BackgroundWorker has a property called WorkerSupportsCancellation . BackgroundWorker具有一个名为WorkerSupportsCancellation的属性。 If this is set to true, you've got another option to cancel the execution. 如果将其设置为true,则可以选择另一个取消执行的选项。

Whenever something wrong happens, you can call backgroundWorker.CancelAsync() , which will set a boolean to true (which is the CancellationPending property in the BackgroundWorker object). 每当发生错误时,都可以调用backgroundWorker.CancelAsync() ,该方法会将布尔值设置为true(这是BackgroundWorker对象中的CancellationPending属性)。

You can then check, during execution, if the CancellationPending is true. 然后,您可以在执行期间检查CancellationPending是否为true。 If so, the worker should stop. 如果是这样,工人应该停下来。

If the worker stops, it'll launch the RunWorkerCompleted event, which will end up in the handler for the method (if any is added). 如果工作程序停止,它将启动RunWorkerCompleted事件,该事件将最终在方法的处理程序中(如果添加了任何事件)。

This way of cancelling can be checked at all instructions, or at the start of a for loop (as in: for (int i = 0; (i < x) && worker.CancellationPending; i++) ; ) 可以在所有指令处或在for循环开始时检查这种取消方式(如: for (int i = 0; (i < x) && worker.CancellationPending; i++) ;

Hope this helps! 希望这可以帮助!

Use the Result prorperty of the DoWorkEventArgs instance you get passed in DoWork: 使用在DoWork中传递的DoWorkEventArgs实例的结果属性:

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
    }
}

and then in RunWorkerCompleted check the Result value and handle accordingly. 然后在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";
    }
}

Notice that Result is of type object. 请注意, Result是object类型。 You can put any instance of a type into it, even your own class, which might be needed if you want to return more fine grained details about what went wrong. 您可以将类型的任何实例放入其中,甚至可以放入您自己的类,如果您想返回关于出问题的更细粒度的详细信息,可能需要使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM