【发布时间】:2019-02-15 16:05:53
【问题描述】:
我有 N 个具有自己的 CancellationTokenSource 的任务。为了跟踪每个任务及其 CancellationTokenSource,我使用了 ConcurrentDictionary。因此,每当我需要取消特定任务时,我都会从 ConcurrentDictionary 中获取该任务的 CancellationTokenSource 并取消它。
问题是每当我取消一项任务时,所有其他任务也会被取消。有什么我在这里遗漏的或任何其他比这更好的实现。示例代码如下。
CancellationTokenSource _serviceCancelSource;
public async Task Start()
{
var services = _serviceRepository.GetAll();
await Task.Run(() =>
{
Parallel.ForEach(services, x => Task.Run(() => Start(x)));
});
}
public async Task Start(Service service)
{
_serviceCancelSource = new CancellationTokenSource();
myConcurrentDictionary.AddOrUpdate(service.Id, _serviceCancelSource, (key, oldValue) => _serviceCancelSource));
var manager = ServiceManagerFactory.Create(service);
Action serviceAction = () => manager.InitializeTaskAsync();
await Task.Run(() => PeriodicTaskFactory.Start(serviceAction, intervalInMilliseconds: service.PollTime, cancelToken: _serviceCancelSource.Token, serviceName: service.ServiceName));
}
public async Task CancelTask()
{
await Task.Run(() =>
{
var serviceId = GetChangedService();
CancellationTokenSource cancelSource;
if (myConcurrentDictionary.TryGetValue(serviceId, out cancelSource))
{
cancelSource.Cancel();
}
});
}
【问题讨论】:
-
为什么将取消令牌存储在
myConcurrentDictionary中,然后在DataService.serviceCancellationTokenMap中搜索?为什么不在Start方法中为serviceCancelSource指定类型?它是课堂上的一个领域吗?一般来说 - 无法使用您提供的代码重现问题。 -
@SergeyShevchenko 我的错。我修改了原始代码以将示例放在这里,并遗漏了一些地方。我已经编辑了代码。 _serviceCancelSource 是正确的,它是类中的一个字段。
-
不确定我是否正确阅读了您的代码,但如果您共享令牌源,那么它将取消所有令牌,因此所有从该源接收令牌的任务。您不需要共享令牌源。但同样,我从阅读您的代码中并不确定是否足以回答这个问题。
-
@Kit 每次我将新的令牌源添加到每个服务的字典中。所以它不被共享。
-
@Raj 我想我的困惑是因为
_serviceCancelSource和serviceCancelSource。当您的字典中存储有源时,为什么需要前一个字段?