在 backgroundworker 中取消长 运行 进程的最佳方法

Best way to cancel long running process inside backgroundworker

快速取消后台工作程序中较长 运行 进程的最佳解决方案是什么? 比如我们有这样的情况:

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            ...

            for (int i = 0; i < items; i++)
            {
                if (_worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    VeryLongRunningProcess();
                }
            }
        }
        
        private void VeryLongRunningProcess()
        {
            var a = Test();
            var b = Test2();
            Thread.Sleep(5000);
            var c = Test3();
        }

在这种情况下,VeryLongRunningProcess() 将不会在按下取消时完成,直到他完成体内的所有内容。

遇到这种情况怎么办?

我试图将 (BackgroundWorker)sender 作为参数传递给 VeryLongRunningProcess() 并在此方法中检查 CancellationPending,但我不知道这种方法是否正确

通常您应该创建 long-running 进程作为“异步”方法(public 异步任务或任务 DoWork())以用于资源分配目的。 “CancelationToken”启用线程、线程池工作项之间的协作取消。也可以传播一个回调委托,当取消令牌取消或函数完成时可以调用它。

如果问题与 worker 一样与 类 隔离了 VeryLongRunningProcess,您可以使用 Func 作为参数并在方法之外保留 worker 访问权限

private void VeryLongRunningProcess(Func<bool> isCancelled)
{
    var a = Test();

    if (isCancelled())
    {
        return;
    }

    var b = Test2();

    if (isCancelled())
    {
        return;
    }

    Thread.Sleep(5000);
    var c = Test3();
}

在您的方法中,您可以根据需要多次检查是否必须取消操作。您可以将 Func 用作其他方法(如 Test1、Test2...)中的参数,如果它们中的任何一个需要很长时间才能完成。

然后,您以这种形式调用您的方法:

VeryLongRunningProcess(() => _worker.CancellationPending);

正如其他人评论的那样,使用 async/await 可能很有趣。

更新

另一种选择是否使用取消的方法:

private void VeryLongRunningProcess(Func<bool> isCancelled = null)
{
    var a = Test();

    // Or: isCancelled != null && isCancelled()
    if (isCancelled?.Invoke() ?? false)
    {
        return;
    }

    // ...
}