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

C#BackgroundProcess:在.RunworkerAsync之前使用.CancelAsync安全吗?,c#,backgroundworker,C#,Backgroundworker,当用户试图双击按钮时,backgroundWorker将启动两次 这是一个好的解决办法吗 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // Some processing here Thread.Sleep(1000); button1.Invoke((MethodInvoker)delegate { button1.Enabled= true; }); } // R

当用户试图双击按钮时,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();
}
您可以使用事件来启用按钮1。而是在
backgroundWorker1\u-DoWork中启用

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           this.button1.Enabled = true;
            //rest of operations
        }
您的代码有什么问题:


您正在启用
\u DoWork
中的按钮,因为
backgroundWorker1.RunWorkerAssync()
将调用
\u DoWork()
在那里,按钮将启用,因此第二次单击也将执行

在使用BackgroundWorker时,您必须注意三个基本事项

  • DoWork:如果需要,您可以处理业务逻辑的执行和工作的取消
  • RunWorkerCompleted:您可以处理执行后任务。在这里,您希望启用按钮,所以应该将适当的代码写入RunWorkerCompleted事件
  • 如果要在任何执行点取消backgroundworker进程,请处理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(); 
    }
    
    private void按钮1\u单击(对象发送者,事件参数e)
    {
    backgroundWorker1.WorkerSupportsScanCellation=true;
    backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
    backgroundWorker1.RunWorkerCompleted+=backgroundWorker1\u RunWorkerCompleted;
    按钮1.启用=错误;
    backgroundWorker1.RunWorkerAsync();
    }
    void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
    {
    Invoke((MethodInvoker)委托{button1.Enabled=true;});
    backgroundWorker1.dowwork-=backgroundWorker1_dowwork;
    backgroundWorker1.RunWorkerCompleted-=backgroundWorker1\u RunWorkerCompleted;
    }
    无效backgroundWorker1\u DoWork(对象发送方,DoWorkerVentargs e)
    {
    对于(int i=0;i<10;i++)
    {
    睡眠(1000);
    AppendTextBox(“点击:+i.ToString()+Environment.NewLine”);
    if(backgroundWorker1.CancellationPending)
    {
    打破
    }
    }
    if(backgroundWorker1.CancellationPending)
    {
    e、 取消=真;
    }            
    }
    公共无效文本框(字符串值)
    {
    如果(需要调用)
    {
    调用(新操作(AppendTextBox),新对象[]{value});
    返回;
    }
    textBox1.Text+=值;
    }
    私有无效按钮2\u单击(对象发送者,事件参数e)
    {
    if(backgroundWorker1.IsBusy)
    backgroundWorker1.CancelAsync();
    }
    

  • 如果工人确实在运行,那么几乎可以肯定不是

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

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

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

    她非常苗条。如果工作进程正在运行,
    RunWorkerAsync
    更有可能抛出
    invalidoOperationException
    ,因为工作进程仍在运行。

    根据我的意见,您应该启用/禁用按钮。在默认状态下启用。当您单击该按钮时,它将被禁用,并且仅在1时启用。过程已经完成。2.进程被取消3。捕获流程中的任何错误。我忘记提到我使用了
    button1.Invoke((MethodInvoker)委托{button1.Enabled=true;})
    可在
    \u DoWork
    中使用你试过我建议的解决办法了吗?您也可以尝试
    按钮1。在
    中调用(..
    )\u runworker completed
    它应该可以工作