[英]Cancellation of multiple tasks in TPL based on return resutl
我有一个场景,我有多个函数可以并行调用,我正在使用TPL执行该任务。 我用过
ConcurrentDictionary<string, List<result>> dictionary = new ConcurrentDictionary<string, List<result>>();
var tasks = Task.Run(()=>
{
new Task(()=> {dictionary.TryAdd("First", CallFirstFunction());});
new Task(()=> {dictionary.TryAdd("Second", CallSecondFunction());});
new Task(()=> {dictionary.TryAdd("Third", CallThirdFunction());});
new Task(()=> {dictionary.TryAdd("Fourth", CallFourthFunction());});
});
现在,我需要等到所有函数都被执行并在并发字典中返回一些结果,这样我就可以将它用于进一步的处理了。但是如果一些返回的结果为空而不管任务顺序,我也想取消任何任务。 如果任何函数返回空结果,我需要同时取消所有剩余的任务。 我已经检查了“CancellationToken”类,但我很困惑在任务中使用它以及如何在任务中共享功能状态。
任何帮助将不胜感激。 最好的祝福
要支持取消,您需要使用CancellationTokenSource。 请参阅https://msdn.microsoft.com/en-us/library/mt674886.aspx
你需要做的是将CancellationTokenSource
传递给你的方法,所以当结果为空时你可以调用CancellationTokenSource.Cancel()
async Task DoWorkAsync()
{
var cts = new CancellationTokenSource();
var ct = cts.Token;
var tasks = new List<Task>
{
Task.Run(() => AddToDictionary("First", () => CallFirstFunction(), cts), ct),
Task.Run(() => AddToDictionary("Second", () => CallSecondFunction(), cts), ct),
Task.Run(() => AddToDictionary("Third", () => CallThirdFunction(), cts), ct),
Task.Run(() => AddToDictionary("Fourth", () => CallFourthFunction(), cts), ct),
};
try
{
await Task.WhenAll(tasks);
}
catch (OperationCanceledException ex)
{
}
}
private void AddToDictionary(string key, Func<List<int>> method, CancellationTokenSource cts)
{
if(cts.IsCancellationRequested)
return;
var result = method.Invoke();
if(!result.Any());
cts.Cancel();
if(!cts.IsCancellationRequested)
dictionary.TryAdd(key, result);
}
此示例假定您调用的操作(CallFirstFunction等)不是异步(不返回任务或任务)。 否则你也应该将CancellationToken
传递给他们并使用ct.ThrowIfCancellationRequested
检查取消
取消任务会生成您需要处理的OperationCanceledException。
当然,当任何方法在另一个方法返回空结果之前已经完成时,那些结果将已经存在于字典中。 如果您需要其他行为,此示例将为您提供有关CancellationTokenSource
如何与Tasks和CancellationTokens相关的一些基本概念
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.