![](/img/trans.png)
[英]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.