[英]How do I execute multiple Tasks using Task Parallel Library and return after the first one to actually return data
[英]How to execute a number of tasks in parallel, and return ASAP when a task completes with a specific result?
我必须执行一定数量的方法,并且以一定值结束的第一个方法必须退出循环。
代码如下所示:
var tasks = new List<Task<bool>>();
tasks.Add(VerificheHandler.RandomString(14));
tasks.Add(VerificheHandler.RandomString(9000));
public bool Test()
{
Parallel.ForEach(tasks, task =>
{
task.Start();
if(task.Result)
{
//exit parallel and kill all
return true;
}
});
}
public async static Task<bool> RandomString(int delay)
{
await Task.Delay(delay);
return true;
}
错误是:
task.Result
Start may not be called on a promise-style task
您可以使用ParallelLoopState.Break提前执行并行循环。 还有一个.Stop()
方法。 Break 将继续执行所有索引,直到调用 break 的索引,而 stop 不会启动较低索引的迭代。 在这两种情况下,循环可能已经开始或完成了更高索引的迭代。
此外,parallel.for/foreach 通常不与任务结合使用。 使方法同步会使它看起来像这样:
public static void Test()
{
Parallel.For(0, 10, (i, state) =>
{
var r = RandomString(100);
if (r)
{
state.Break();
}
});
}
public static bool RandomString(int delay)
{
Thread.Sleep(delay);
return true;
}
您提供的示例无法编译,因为您不能将Task<bool>
存储在Task<string>
的集合中。
如果我正确理解您的问题,那么您正在寻找解决方案:
为了实现这样的解决方案,我们必须使用CancellationToken
来停止任何正在进行的操作。 所以修改后的RandomString
可能如下所示:
public static async Task<string> RandomString(int delay, CancellationToken token)
{
try
{
await Task.Delay(delay, token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Task has been cancelled " + delay);
return null;
}
Console.WriteLine("Finished " + delay);
return "Random " + delay;
}
CancellationToken
参数,然后将其传递给Task.Delay
。
Task.Delay
期间有取消,那么我们浅化OperationCanceledException
并打印出一些调试信息。为了能够冷启动这个方法,我们可以在它周围引入一个简单的包装器:
public static Func<CancellationToken, Task<string>> RandomStringWrapper(int delay)
=> (ct) => RandomString(delay, ct);
RandomString
,而是返回一个 function ,它需要一个CancellationToken
。CancellationToken
时,任务就会运行。所以,现在我们可以引入一个足够通用的扩展方法来支持多种不同的异步方法:
public static class TaskEx
{
public static async Task RunUntil<T>(this IEnumerable<Func<CancellationToken, Task<T>>> asyncFunctions, T exitCondition, CancellationTokenSource cts)
{
var jobs = asyncFunctions.Select(fn => fn(cts.Token)).ToList();
while (true)
{
var fastest = await Task.WhenAny(jobs);
if (fastest.Result.Equals(exitCondition))
{
cts.Cancel(true);
return;
}
jobs.Remove(fastest);
if (jobs.Count == 0)
return;
}
}
}
asyncFunctions
:它是函数的集合。 每个人都希望CancellationToken
返回一个Task<T>
。exitCondition
:顾名思义...cts
: CancellationToken
提供程序。CancellationToken
传递给异步方法来启动它们。fastest
完成。fastest
的结果等于exitCondition
则我们取消剩余的任务。jobs
并重新运行相同的循环,直到有要执行的作业。现在,让我们把所有这些放在一起:
static async Task Main(string[] args)
{
var cts = new CancellationTokenSource();
var tasks = new[] { RandomStringWrapper(14), RandomStringWrapper(600), RandomStringWrapper(500) };
await tasks.RunUntil("Random 500", cts);
}
output 将是:
Finished 14
Finished 500
Task has been cancelled 600
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.