为什么后台工作者取消按钮不能取消后台工作者操作?

3
我在Form1的顶部添加了这两行代码:
backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.WorkerSupportsCancellation = true; 

在按钮点击事件的开始处,我添加了以下内容:
timer2.Enabled = true;
if (this.backgroundWorker1.IsBusy == false)
            {
                this.backgroundWorker1.RunWorkerAsync();
            }

这是DoWork事件:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }  
            if (filesContent.Length > 0)
            {
                for (int i = 0; i < filesContent.Length; i++)
                {
                    File.Copy(filesContent[i], Path.Combine(contentDirectory, Path.GetFileName(filesContent[i])), true);
                }
            }
            WindowsUpdate();
            CreateDriversList();
            GetHostsFile();
            Processes();
        }

然后是工作完成事件:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                this.Diagnose.Text = "THIS OPERATION HAS BEEN CANCELLED";
            }
            else if (!(e.Error == null))
            {
                this.Diagnose.Text = ("Error: " + e.Error.Message);
            }
            else
            {
                processfinish = true;
            }
        }

最终按钮点击取消事件:
private void CancelOperation_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();  
        }

当我点击取消按钮时,我使用了一个断点来查看它是否执行到了 CancelAsync(); 但是然后它就直接跳到了 timer2 的 tick 事件并继续工作。 timer2 是在我点击开始按钮后开始工作的。

这是 timer2 的 tick 事件:

private void timer2_Tick(object sender, EventArgs e)
        {
            timerCount += 1;
            TimerCount.Text = TimeSpan.FromSeconds(timerCount).ToString();
            TimerCount.Visible = true;
            if (processfinish == true)
            {
                timer2.Enabled = false;
                timer1.Enabled = true;
            }                           
        }

当我点击“取消”按钮时,为什么操作并没有停止并继续正常执行? 在“取消”按钮中,是否需要处理/清理任何对象或后台工作器?
以下是我在DoWork中所做的:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            while (true)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;  
                    if (filesContent.Length > 0)
                    {
                        for (int i = 0; i < filesContent.Length; i++)
                        {
                            File.Copy(filesContent[i], Path.Combine(contentDirectory, Path.GetFileName(filesContent[i])), true);
                        }
                    }
                    WindowsUpdate();
                    CreateDriversList();
                    GetHostsFile();
                    Processes();
                }
            }
        }

并且取消按钮:
private void CancelOperation_Click(object sender, EventArgs e)
        {
            backgroundWorker1.CancelAsync();
            timer2.Enabled = false;
        }

但是现在在 DoWork 中我没有返回值;所以当我点击取消按钮时,它永远不会到达完成事件,并且永远不会显示消息 this.Diagnose.Text = "THIS OPERATION HAS BEEN CANCELLED";

如果现在加上返回值;那么 DoWork 中的其余代码将成为无法到达的代码

那么怎么办呢?

2个回答

7
因为你的DoWork事件在开始进行所有重度工作之前检查了CancellationPending属性,所以正确的方法是在循环内部检查此属性。同时请注意,如果你只是在复制一些非常大的文件,但想在它正在复制文件时取消,你需要编写可以被取消的代码来完成复制。

我现在正在使用一个循环,但仍然不太好。我更新了我的问题并附上了我所做的内容。 - DanielVest
取消操作不仅适用于复制文件循环,如果在DoWork事件的其他函数中间,也应该取消整个操作。因此,我使用了While(true)循环。 - DanielVest

1
你在错误的阶段检查了CancellationPending。
尝试类似这样的方式:;
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        if (filesContent.Length > 0)
        {
            for (int i = 0; i < filesContent.Length; i++)
            {
                if (worker.CancellationPending)
                {
                   e.Cancel = true;
                   return;
                }  
                File.Copy(filesContent[i], Path.Combine(contentDirectory, Path.GetFileName(filesContent[i])), true);
            }
        }

        if (!worker.CancellationPending)
            WindowsUpdate();

        if (!worker.CancellationPending)
           CreateDriversList();

        if (!worker.CancellationPending)
           GetHostsFile();

        if (!worker.CancellationPending)
           Processes();

        if (worker.CancellationPending)
            e.Cancel = true;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接