异步任务取消最佳做法:用户与程序

本文关键字:用户 程序 任务 取消 最佳 异步 | 更新日期: 2023-09-27 18:31:59

我正在开发一个库,该库在UI线程上执行一些懒惰的空闲后台工作(由于遗留的COM使用,它必须如此)。使用应用可以通过取消令牌取消任务,也可以由于用户操作(通过 IUserFeedback.Continue)显式取消任务。我正在尝试遵循 MSDN 模式进行任务取消。

我的问题是,我是否应该像IdleWorker1那样区分用户(和返回false)和调用应用程序(抛出)的取消。还是我应该平等对待这两种情况并像IdleWorker2一样扔掉?

我对界面的设计者没有任何严格的要求(任务基本上是永无止境的,所以他们只关心到目前为止实际完成了多少工作,他们通过IUserFeedback.Continue接收进度)。

简而言之,IdleWorker1

interface IUserFeedback
{
    bool Continue(int n);
}
class IdleWorker1
{
    public async Task<bool> DoIdleWorkAsync(CancellationToken ct, int timeSlice, IUserFeedback feedback)
    {
        bool more = true;
        int n = 0;
        while (more)
        {
            ct.ThrowIfCancellationRequested();
            more = feedback.Continue(++n);
            await Task.Delay(timeSlice);
        }
        return more;
    }
}

空闲工人2

class IdleWorker2
{
    public async Task DoIdleWorkAsync(CancellationToken ct, int timeSlice, IUserFeedback feedback)
    {
        int n = 0;
        for (;;)
        {
            ct.ThrowIfCancellationRequested();
            if (!feedback.Continue(++n))
                throw new TaskCanceledException();
            await Task.Delay(timeSlice);
        }
    }
}

异步任务取消最佳做法:用户与程序

我认为

,如果您不需要区分两种类型的取消,那么取消的方法甚至不应该知道谁取消了它。

为此,您将有一个CancellationTokenSource用于应用程序取消,另一个用于用户取消。然后,您可以使用CreateLinkedSource()将它们合并为一个,并将其令牌传递给该方法。