【问题标题】:Stopping background worker停止后台工作人员
【发布时间】:2013-04-17 09:55:45
【问题描述】:

我的应用程序使用后台工作程序在循环中执行一些工作。我有它,以便在每次循环迭代时,它检查取消挂起是否为真,如果是,则中断循环。好的,我的应用程序在完成当前循环迭代后停止处理。问题是我认为后台工作人员仍在运行 - 如果我单击按钮再次开始处理,我会收到一个错误提示后台工作人员正忙。

我打算处置工人,但它是在表单运行时创建的,所以如果我处置它,它就不会再开始工作了。我真正想做的是告诉后台工作人员它已完成,如果我点击“停止处理”按钮,那么当我点击开始按钮时它就可以再次开始处理了!

我打算试试这个:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (!backgroundWorker1.CancellationPending) 
    {
        // Start processing in a background thread so the GUI remains responsive,
        // pass in the name of the text file produced by 
        // PFDR FilenameLogic(txtLetterType.Text); 
    } 
}

【问题讨论】:

  • 您是否在等待RunWorkerCompleted 事件以启用开始处理按钮?
  • “我有它,以便在每次循环迭代时,它检查取消挂起是否为真,如果是,则中断循环。”当取消挂起为真时,您是否将 DoWorkEventArgs e 参数 Cancel 属性设置为真? => e.Cancel = true;

标签: c# .net backgroundworker


【解决方案1】:

创建worker时,将worker.WorkerSupportsCancellation设置为true。现在DoWork 处理程序中,您必须定期(最常见的是,在某个循环的开始等)检查worker.CancellationPending - 如果它是真的,设置e.Cancel = true;(这样你可以区分完成和取消)、清理和退出(return;)。现在您的取消按钮可以调用worker.CancelAsync(); 并且它会正确操作。

【讨论】:

  • 那么如何定期检查状态呢?我打算使用这个: private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while (!backgroundWorker1.CancellationPending) { //在后台线程中开始处理,以便 GUI 保持响应,传入由生成的文本文件的名称PFDR FilenameLogic(txtLetterType.Text); } } 但它会起作用吗?
  • @user1779064 没有处理程序的具体示例,这很难回答。但不要循环直到它被取消 - 否则它永远不会完成正常(如果你明白我的意思)。通常,工作人员正在处理已知数量的工作 - 通常涉及某种 forforeach 循环 - 其中顶部是检查取消的理想位置。
【解决方案2】:

与 Marc Gravell 的答案相同,但您似乎没有遵循。

你设置的是 e.cancel = true 吗?

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

【讨论】:

    【解决方案3】:

    我几乎找不到一个很好的方法来取消 Backgroundworker 通过停止按钮

    我的应用是这样的,两个按钮和一个进度条:

    按下停止按钮后是这样的:

    对于点击开始按钮的方法,代码检查BGW是否忙。如果没有启动 BGW:

    private void btnStart_Click(object sender, EventArgs e)
        {
    
    
            //BGW
            if (!backgroundWorker1.IsBusy)
            {
    
                backgroundWorker1.RunWorkerAsync();
    
            }
    
    
    
        }
    

    停止按钮调用以下方法,该方法将标志 CancellationPending 设置为 true:

            private void btnStop_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();
        }
    

    该标志可以用在backgroundWorker1_DoWork方法中,该方法负责处理高耗时函数:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 100; i++)
            {
    
                backgroundWorker1.ReportProgress(i);
                Thread.Sleep(100);
    
    
    
                if (backgroundWorker1.CancellationPending && backgroundWorker1.IsBusy)
                {
                    e.Cancel = true;
                    return;
                }
            }
        }
    

    现在是棘手的部分,因为在关闭额外线程之前,您必须检查 backgroundWorker1_ProgressChanged 中的 e 对象是否被取消! !!!否则,您将收到 错误

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            int i = 0;
    
            if (!e.Cancelled)
            {
                i = (int)(e.Result);
            }
            else
            {
                i = 0;
            }
    
            // Check to see if an error occurred in the
            // background process.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
                return;
            }
    
            // Check to see if the background process was cancelled.
            if (e.Cancelled)
            {
                MessageBox.Show("Processing cancelled.");
                return;
            }
    
            // Everything completed normally.
            // process the response using e.Result
            MessageBox.Show("Processing is complete.");
    
        }
    

    额外信息: 不要忘记设置这些 Backgroundworker 标志:

                //Set WorkerReportsProgress true - otherwise no ProgressChanged active
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
    

    如果这个小教程有帮助 --> 点赞

    【讨论】:

      【解决方案4】:

      我似乎已经解决了这个错误 - 在我投入一段时间的 Backgroundworker DoWork 方法中 CancelPending 不正确,当它为真时我设置 e.Cancel = true 现在似乎工作正常!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多