C#BackgroundProcess:在.RunworkerAsync之前使用.CancelAsync是否安全?

时间:2016-02-19 06:46:41

标签: c# backgroundworker

当用户尝试双击按钮时, backgroundWorker 将启动两次。

这是一个很好的解决方法吗?

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // Some processing here
    Thread.Sleep(1000);
    button1.Invoke((MethodInvoker)delegate { button1.Enabled= true; });
}

// Run backgroundProcess
private void button1_Click(object sender, EventArgs e)
{
    this.button1.Enabled = false;
    backgroundWorker1.CancelAsync();
    backgroundWorker1.RunWorkerAsync();
}

3 个答案:

答案 0 :(得分:0)

您可以使用backgroundWorker1_RunWorkerCompleted事件启用button1。而是在backgroundWorker1_DoWork

中启用
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           this.button1.Enabled = true;
            //rest of operations
        }

您的代码有什么问题:

您可以启用_DoWork中的按钮,这意味着更少,因为backgroundWorker1.RunWorkerAssync();将调用_DoWork()按钮启用,因此第二次点击也会被执行。

答案 1 :(得分:0)

当您打算使用BackgrounWorker时,您必须处理三件基本事情。

  1. DoWork:如果需要,您可以处理业务逻辑的执行和取消工作。
  2. RunWorkerCompleted:您可以处理后期执行任务。在这里,您需要启用按钮,因此您应该将相应的代码写入RunWorkerCompleted Event。
  3. 如果要在任何执行点取消后台工作进程,请处理WorkerSupportsCancellation属性。

     private void button1_Click(object sender, EventArgs e)
    {
        backgroundWorker1.WorkerSupportsCancellation = true;            
        backgroundWorker1.DoWork += backgroundWorker1_DoWork;
        backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
        button1.Enabled = false;
        backgroundWorker1.RunWorkerAsync();
    }
    
    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        button1.Invoke((MethodInvoker)delegate { button1.Enabled = true; });
        backgroundWorker1.DoWork -= backgroundWorker1_DoWork;
        backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_RunWorkerCompleted;
    }
    
    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);                
            AppendTextBox( "Hit: " + i.ToString() + Environment.NewLine);
            if (backgroundWorker1.CancellationPending)
            {
                break;
            }
    
        }
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
        }            
    }
    public void AppendTextBox(string value)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
            return;
        }
        textBox1.Text += value;
    }
    private void button2_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.IsBusy)
            backgroundWorker1.CancelAsync(); 
    }
    

答案 2 :(得分:0)

如果工人实际上在跑步,那几乎肯定不会。

取消是合作的。调用CancelAsync只会将CancellationPending标志设置为true。由后台工作人员定期检查此标志并响应取消。

正在运行的工作人员在这两行代码之间的时间间隔内获得检查该标志,检查并响应的适当点的可能性:

backgroundWorker1.CancelAsync();
backgroundWorker1.RunWorkerAsync();

非常苗条。由于工人仍在运行,RunWorkerAsync将抛出InvalidOperationException的可能性更大(如果工人正在运行)。