使用单个取消令牌添加中止所有任务
Adding abort all tasks using a single cancellation token
我收到了可以同时执行多项任务的服务。我被指派添加一个中止选项,该选项应该结束所有当前的 运行 任务。因为系统已经实现,将 CancellationTokenSource 传递给每个任务是有问题的,所以我所做的是创建一个所有任务都会监听的单一取消。当中止接收时,该令牌将发送取消,然后将创建一个新的 CancellationTokenSource 实例。
我无法验证所有任务,直到中止结束 在 启动新的 CancellationTokenSource 实例之前。
几个问题:
起初我以为TokenSource.Cancel()只是一个发送的事件,但它似乎被卡住了"on high",所以任何具有相同令牌的新任务都会被取消也是,是真的吗?
理想情况下,每个任务都有自己的取消令牌(对吗?),问题是谁需要持有该令牌?谁调用了任务或任务本身?因为一旦发送取消,我将需要永远保留该令牌,因为我无法确定任务何时到达退出点..
是否有一种已经实施的方法来监视所有当前 运行 任务,以便在发送取消时我会确保所有任务都已结束,然后再允许任何新任务?我是用信号灯做的,但它看起来像一个糟糕的 sulotion..
对于新手的问题,我深表歉意,我已经实现了我所需要的并且它有效,但质量远低于标准,我希望以正确的方式改进它。
任务没有收到任何取消。它只是令牌的状态更改。任务必须watch令牌,如果有取消request那么任务可能会取消操作
每个任务都有自己的token,因为CancellationToken
是一个struct
,会按值复制。为了观察令牌(见 1.),任务必须保留令牌。
不可以,您必须等待任务,不能强制取消任务。使用取消操作,您只需发送取消请求,运行ning 任务可能会取消或成功完成(取决于实现)。只有尚未开始的任务(等待 运行)将被调度程序取消(它们根本不会开始)
作为示例,您正在寻找一个非常简单的示例,了解如何实现此类取消
原始服务
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;
}
}
我收到了可以同时执行多项任务的服务。我被指派添加一个中止选项,该选项应该结束所有当前的 运行 任务。因为系统已经实现,将 CancellationTokenSource 传递给每个任务是有问题的,所以我所做的是创建一个所有任务都会监听的单一取消。当中止接收时,该令牌将发送取消,然后将创建一个新的 CancellationTokenSource 实例。 我无法验证所有任务,直到中止结束 在 启动新的 CancellationTokenSource 实例之前。
几个问题:
起初我以为TokenSource.Cancel()只是一个发送的事件,但它似乎被卡住了"on high",所以任何具有相同令牌的新任务都会被取消也是,是真的吗?
理想情况下,每个任务都有自己的取消令牌(对吗?),问题是谁需要持有该令牌?谁调用了任务或任务本身?因为一旦发送取消,我将需要永远保留该令牌,因为我无法确定任务何时到达退出点..
是否有一种已经实施的方法来监视所有当前 运行 任务,以便在发送取消时我会确保所有任务都已结束,然后再允许任何新任务?我是用信号灯做的,但它看起来像一个糟糕的 sulotion..
对于新手的问题,我深表歉意,我已经实现了我所需要的并且它有效,但质量远低于标准,我希望以正确的方式改进它。
任务没有收到任何取消。它只是令牌的状态更改。任务必须watch令牌,如果有取消request那么任务可能会取消操作
每个任务都有自己的token,因为
CancellationToken
是一个struct
,会按值复制。为了观察令牌(见 1.),任务必须保留令牌。不可以,您必须等待任务,不能强制取消任务。使用取消操作,您只需发送取消请求,运行ning 任务可能会取消或成功完成(取决于实现)。只有尚未开始的任务(等待 运行)将被调度程序取消(它们根本不会开始)
作为示例,您正在寻找一个非常简单的示例,了解如何实现此类取消
原始服务
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;
}
}