我说过一个名为:
的界面interface IExecutor {
String Name { get; }
Task<int> Execute();
}
它的两个实现(细节是无关紧要的,您可以假设方法标记为异步并按预期工作)。每个实现需要2-3秒才能运行,并且IExecutor将会有2到5个实现
我有一个控制器需要运行所有执行程序并将结果作为ExecutorResult对象返回。 ExecutorResult的地方是:
class ExecutorResult {
int Result; // assume usual get n set
String ExecutorName;
}
理想情况下,这应该以扇出方式进行。
我想到了以下方法:
List<Task<int>> tasks = new List<Task<int>>();
foreach(var executor in executors) {
tasks.Add(executor.Execute());
}
var results = Task.WhenAll(tasks);
我对这种方法的问题是我不确定这是否是ASP WebAPI应用程序中的最佳实践。另外 - 鉴于我想返回Result对象 - 其中Result需要执行者的名称,而执行上述解决方案的int结果在for循环之外不起作用我不再能够访问每个对象的Name属性执行程序。
那么这种方法的最佳实践是什么(再次 - 给定一个Web Api应用程序而不是控制台应用程序)
答案 0 :(得分:2)
您已经拥有的是最佳实践。你正在做的是异步并发,最好用Task.WhenAll
完成。
请注意代码:
List<Task<int>> tasks = new List<Task<int>>();
foreach(var executor in executors) {
tasks.Add(executor.Execute());
}
var results = Task.WhenAll(tasks);
可以简化为:
var results = Task.WhenAll(executors.Select(e => e.Execute()));
尽管有无数个例子使用List<Task>
,但实际上你并没有明确地建立一个。
答案 1 :(得分:1)
如果我理解正确,你会找到这样的东西:
var tasks = new List<Task<ExecutorResult>>();
foreach (var executor in executors)
{
tasks.Add(((Func<IExecutor, Task<ExecutorResult>>)(
async (e) => new ExecutorResult
{
ExecutorName = e.Name,
Result = await e.Execute()
}))(executor));
}
var results = Task.WhenAll(tasks);
或者,按照Stephen Clearly的建议:
var results = Task.WhenAll(
from executor in executors
select ((Func<IExecutor, Task<ExecutorResult>>)(
async (e) => new ExecutorResult
{
ExecutorName = e.Name,
Result = await e.Execute()
}))(executor))
);
答案 2 :(得分:1)
这对我有用:
public class Executor : IExecutor
{
public String Name { get; set;}
public async Task<int> Execute()
{
Console.WriteLine("Executing " + Name);
await Task.Delay(3000);
Console.WriteLine("Finished Executing " + Name);
return 0;
}
}
public async Task<ExecutorResult> Execute(IExecutor executor)
{
return new ExecutorResult { ExecutorName = executor.Name,
Result = await executor.Execute() };
}
public async Task MainAsync()
{
var executors = new List<IExecutor>
{
new Executor { Name = "Executor1" },
new Executor { Name = "Executor2" },
new Executor { Name = "Executor3" }
};
List<Task<ExecutorResult>> tasks = new List<Task<ExecutorResult>>();
foreach(var executor in executors)
{
tasks.Add(Execute(executor));
}
var results = await Task.WhenAll(tasks);
}
void Main()
{
MainAsync().Wait();
}