繁体   English   中英

使用单个取消令牌添加中止所有任务

[英]Adding abort all tasks using a single cancellation token

我获得了可以同时执行许多任务的服务。 我被分配添加一个中止选项,该选项应终止所有当前正在运行的任务。 因为系统已经实现,所以将CancellationTokenSource传递给每个任务都是有问题的,所以我要做的是创建一个单一的任务,所有任务都将监听取消消息。 当中止接收时,该令牌将发送取消消息,然后将创建一个新的CancellationTokenSource实例。 我无法验证所有任务,直到中止在启动CancellationTokenSource的新实例之前结束为止。

几个问:

  1. 起初,我认为TokenSource.Cancel()只是发送的一个事件,但似乎被卡在“高位”,因此具有相同令牌的任何新任务也将被取消,这是真的吗?

  2. 理想情况下,每个任务都有自己的取消令牌(对吗?),问题是谁需要持有该令牌? 谁调用了任务或任务本身? 因为一旦发送了取消通知,我将需要永久保留该令牌,因为我无法确定任务何时到达出口点。

  3. 有没有已经实现的方法来监视所有当前正在运行的任务,因此当发送取消消息时,我将确保在允许任何新任务之前所有任务都已结束? 我用信号灯来做,但是看起来像个可怕的灵魂。

抱歉,对于新手问题,我已经实现了所需的功能,并且可以正常工作,但是质量远低于标准,我希望以正确的方式进行改进。

  1. 该任务没有收到任何取消。 它只是令牌的状态更改。 任务必须监视令牌,如果有取消请求,则任务可能会取消操作。

  2. 每个任务都有自己的令牌,因为CancellationToken是一个struct ,将按值复制。 为了观看令牌(请参阅1.),任务必须保留令牌。

  3. 不,您必须等待任务,并且不能强制取消任务。 使用“取消”操作,您仅发送取消请求,并且正在运行的任务可能会取消或成功完成(取决于实现)。 调度程序仅取消尚未启动的任务(等待运行)(它们根本不会启动)

例如,如何实现这种取消,您在这里寻找一个非常简单的示例

原始服务

public interface IFooService
{
    Task DoAsync( CancellationToken cancellationToken );
}

和将处理取消的

public interface ICancelableFooService : IFooService
{
    Task CancelAsync();
}

public class CancelableFooService : ICancelableFooService
{
    private readonly IFooService _foo_service;
    private readonly object _sync = new object();
    private List<Task> _createdtasks = new List<Task>();
    private CancellationTokenSource _cts = new CancellationTokenSource();

    public CancelableFooService(IFooService foo_service)
    {
        _foo_service = foo_service;
    }

    public async Task CancelAsync()
    {
        _cts.Cancel();
        var t = Task.WhenAll( _createdtasks );
        try
        {
            await t;
        }
        catch { /* we eat all exceptions here */ }
        lock( _sync )
        {
            _cts = new CancellationTokenSource();
            _createdtasks.Clear();
        }
    }

    public Task DoAsync( CancellationToken cancellationToken )
    {
        lock(_sync)
        {
            var cts = CancellationTokenSource.CreateLinkedTokenSource( _cts.Token, cancellationToken );
            var token = cts.Token;
            var task = _foo_service.DoAsync( token );
            _createdtasks.Add( task );
        }
        return task;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM