C # BackgroundWorker.CancelAsync () против DoWorkEventArgs.Cancel - PullRequest
0 голосов
/ 31 октября 2019

Я хочу использовать значение RunWorkerCompletedEventArgs.Cancelled в моем обработчике завершения BackgroundWorker, но в документации неясно, как BackgroundWorker.CancelAsync() и DoWorkEventArgs.Cancel (в фоновом работнике работают с обработчиком) будут влиять на него. Они функционально одинаковы?

Например, это ...

private void _Worker_DoWork(object sender, DoWorkEventArgs e)
{
    (sender as BackgroundWorker).CancelAsync();
}

... эквивалентно этому?

private void _Worker_DoWork(object sender, DoWorkEventArgs e)
{
    e.Cancel = true;
}

Приведет ли последний кпоследующие оценки CancellationPending() оценивать как верные? Кроме того, если фоновый работник отменяется извне (т. Е. myBW.CancelAsync(); вне обработчика do work), e.Cancel = false приведет к тому, что оценка CancellationPending() будет ложной?

Ответы [ 2 ]

1 голос
/ 31 октября 2019

BackgroundWorker.CancelAsync() установит значение BackgroundWorker.CancellationPending в значение true, поэтому код DoEvent может проверить его.

DoWorkEventArgs.Cancel должен сообщить RunWorkerCompleted Event, что процесс был отменен. Вы не должны использовать результат операции, которая была прервана или завершилась в Exception. Если для DoWorkEventArgs.Cancel установлено значение true, для RunWorkerCompletedEventArgs.Canceled установлено значение true. Который также заставит RunWorkerCompletedEventArgs.Result генерировать исключение при обращении .

У меня есть довольно старый пример кода, когда я изучал Multithrading с BGW. Это должно помочь вам.

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
    if (!bgwPrim.IsBusy)
    {
        //Prepare ProgressBar and Textbox
        int temp = (int)nudPrim.Value;
        pgbPrim.Maximum = temp;
        tbPrim.Text = "";

        //Start processing
        bgwPrim.RunWorkerAsync(temp);
    }
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
    if (bgwPrim.IsBusy)
    {
        bgwPrim.CancelAsync();
    }
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
    int highestToCheck = (int)e.Argument;
    //Get a reference to the BackgroundWorker running this code
    //for Progress Updates and Cancelation checking
    BackgroundWorker thisWorker = (BackgroundWorker)sender;

    //Create the list that stores the results and is returned by DoWork
    List<int> Primes = new List<int>();


    //Check all uneven numbers between 1 and whatever the user choose as upper limit
    for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
    {
        //Report progress
        thisWorker.ReportProgress(PrimeCandidate);
        bool isNoPrime = false;

        //Check if the Cancelation was requested during the last loop
        if (thisWorker.CancellationPending)
        {
            //Tell the Backgroundworker you are canceling and exit the for-loop
            e.Cancel = true;
            break;
        }

        //Determin if this is a Prime Number
        for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
        {
            if (PrimeCandidate % j == 0)
                isNoPrime = true;
        }

        if (!isNoPrime)
            Primes.Add(PrimeCandidate);
    }

    //Tell the progress bar you are finished
    thisWorker.ReportProgress(highestToCheck);

    //Save Return Value
    e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pgbPrim.Value = pgbPrim.Maximum;
    this.Refresh();

    if (!e.Cancelled && e.Error == null)
    {
        //Show the Result
        int[] Primes = (int[])e.Result;

        StringBuilder sbOutput = new StringBuilder();

        foreach (int Prim in Primes)
        {
            sbOutput.Append(Prim.ToString() + Environment.NewLine);
        }

        tbPrim.Text = sbOutput.ToString();
    }
    else 
    {
        tbPrim.Text = "Operation canceled by user or Exception";
    }
}
#endregion

Лично я считаю, что класс BackgroundWorker в графическом интерфейсе хорошо подходит для многозадачных "тренировочных колес".

0 голосов
/ 31 октября 2019

Нет, они не одинаковы. Метод CancelAsync () запускается из-за пределов кода «backgroundworker». «CancellationPending» можно проверить в теле «DoWork», а «e.Cancel» установить в «DoWork» для использования в методе «Completed».
Для получения дополнительной информации см. Страницу ниже:
(https://www.c -sharpcorner.com / uploadfile / mahesh / backgroundworker-in-C-Sharp / )

...