简体   繁体   English

C# BackgroundWorker.CancelAsync() 与 DoWorkEventArgs.Cancel

[英]C# BackgroundWorker.CancelAsync() vs DoWorkEventArgs.Cancel

I want to use the RunWorkerCompletedEventArgs.Cancelled value in my BackgroundWorker completed handler, but the documentation isn't clear how how BackgroundWorker.CancelAsync() and DoWorkEventArgs.Cancel (in the background worker do work handler) will each effect it.我想在我的 BackgroundWorker 完成的处理程序中使用RunWorkerCompletedEventArgs.Cancelled值,但文档不清楚BackgroundWorker.CancelAsync()DoWorkEventArgs.Cancel (在后台工作人员执行工作处理程序中)将如何影响它。 Are they functionally the same?它们在功能上是否相同?

For example, is this...例如,这是...

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

...equivalent to this? ……相当于这个?

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

Will the latter result in subsequent evaluations of CancellationPending() to evaluate as true?后者是否会导致后续对CancellationPending()的评估结果为真? Also, if the background worker is cancelled externally (ie myBW.CancelAsync(); outside the do work handler), will e.Cancel = false cause an evaluation of CancellationPending() to be false?此外,如果后台工作人员在外部被取消(即myBW.CancelAsync();在 do 工作处理程序之外), e.Cancel = false是否会导致对CancellationPending()的评估为假?

BackgroundWorker.CancelAsync() will set the value of BackgroundWorker.CancellationPending to true, so the DoEvent code can check it. BackgroundWorker.CancelAsync()会将BackgroundWorker.CancellationPending的值设置为 true,因此 DoEvent 代码可以检查它。

DoWorkEventArgs.Cancel is there to tell RunWorkerCompleted Event that the process was Canceled. DoWorkEventArgs.Cancel用于告诉 RunWorkerCompleted Event 进程已取消。 You are not supposed to use the result of a operation that was aborted or ended in Exception.您不应该使用被中止或以异常结束的操作的结果。 Setting DoWorkEventArgs.Cancel to true will set RunWorkerCompletedEventArgs.Canceled to true.RunWorkerCompletedEventArgs.Canceled DoWorkEventArgs.Cancel为 true。 Wich will also force RunWorkerCompletedEventArgs.Result to throw an exception if accessed .如果访问,Wich 还将强制RunWorkerCompletedEventArgs.Result 抛出异常

I have some pretty old example code from when I learned Multithrading with BGW.当我使用 BGW 学习多线程时,我有一些非常古老的示例代码。 It should help you.它应该可以帮助你。

#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

Personally I consider the BackgroundWorker class in a GUI to be good Multitasking "Training Wheels".我个人认为 GUI 中的 BackgroundWorker class 是很好的多任务“训练轮”。

No, they are not the same.不,它们不一样。 The "CancelAsync()" method runs from outside of the "backgroundworker"'s code. “CancelAsync()”方法从“backgroundworker”的代码之外运行。 The "CancellationPending" can be check in the "DoWork" body and "e.Cancel" is set in "DoWork" to be used in the "Completed" method.可以在“DoWork”主体中检查“CancellationPending”,并在“DoWork”中设置“e.Cancel”以在“Completed”方法中使用。
Please see the page below for more information:请参阅以下页面了解更多信息:
( https://www.c-sharpcorner.com/uploadfile/mahesh/backgroundworker-in-C-Sharp/ ) https://www.c-sharpcorner.com/uploadfile/mahesh/backgroundworker-in-C-Sharp/

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

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