Dor*_*rey 1 .net c# parallel-processing task
我们有不同的长期程序,成功和不成功的结果。我们希望并行运行这些任务,并返回用户第一个成功的结果。停止其他任务也会很棒。
我试过 Task.WhenAny 和 Parallel.ForEach 方法。第一个不能真正检查成功。第二个做了很多额外的工作。
我的片段在这里:
public static class Program
{
public static void Main(string[] args)
{
//FirstTry().Wait();
SecondTry().Wait();
}
public static async Task FirstTry()
{
var variants = Enumerable.Range(1, 20).ToList();
// first try
var tasks = variants.ConvertAll(async v => await LongProcedureTrueIfSuccess(v));
var completed = await Task.WhenAny(tasks);
var result = (await completed) ? "Good" : "Bad";
Console.WriteLine("Result is " + result);
}
public static async Task SecondTry()
{
var variants = Enumerable.Range(1, 20).ToList();
CancellationTokenSource cts = new CancellationTokenSource();
ConcurrentBag<bool> bag = new ConcurrentBag<bool>();
Parallel.ForEach(variants, (v,state) =>
{
var r = LongProcedureTrueIfSuccess(v).Result;
if (r)
{
bag.Add(r);
state.Stop();
}
});
var result = (bag.FirstOrDefault()) ? "Good" : "Bad";
Console.WriteLine("Result is " + result);
}
public static async Task<bool> LongProcedureTrueIfSuccess(int i)
{
await Task.Delay(1000); //Processing
Console.WriteLine("We know result");
if (i == 5)
return true;
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
https://dotnetfiddle.net/Imrrto
最好的预期结果是:
We know result
Result is Good
Run Code Online (Sandbox Code Playgroud)
但是我们有
We know result
Result is Bad
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
Run Code Online (Sandbox Code Playgroud)
在第一种情况下和
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
We know result
Result is Good
Run Code Online (Sandbox Code Playgroud)
第二次
您可以保留未完成任务的列表,并用于Task.WhenAny()等待其中一项任务完成。然后你可以检查任务的结果,看看它是否成功。
如果不成功,请将其从任务列表中删除,然后重试。继续进行,直到任务成功或所有任务都不成功为止。
例如(任务只返回一个布尔值来表示成功):
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static async Task Main()
{
// Make your array of tasks.
var tasks = new List<Task<bool>>
{
someTask(1000, false),
someTask(2000, false),
someTask(3000, true),
someTask(4000, false),
};
while (tasks.Count > 0)
{
var completed = await Task.WhenAny(tasks);
if (completed.Result) // Successful?
{
Console.WriteLine("A task completed successfully");
return;
}
Console.WriteLine("A task completed unsuccessfully");
tasks.Remove(completed);
}
Console.WriteLine("No tasks completed successfully");
}
static async Task<bool> someTask(int delay, bool result)
{
await Task.Delay(delay);
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)
或者有一些取消支持:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static async Task Main()
{
// Make your array of tasks.
var factory = new CancellationTokenSource();
var tasks = new List<Task<bool>>
{
someTask(1000, false, factory.Token),
someTask(2000, false, factory.Token),
someTask(3000, true, factory.Token),
someTask(4000, false, factory.Token),
};
while (tasks.Count > 0)
{
var completed = await Task.WhenAny(tasks);
if (completed.Result) // Successful?
{
Console.WriteLine("A task completed successfully");
factory.Cancel();
return;
}
Console.WriteLine("A task completed unsuccessfully");
tasks.Remove(completed);
}
Console.WriteLine("No tasks completed successfully");
}
static async Task<bool> someTask(int delay, bool result, CancellationToken cancellation)
{
await Task.Delay(delay, cancellation);
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
785 次 |
| 最近记录: |