2015-09-04 33 views
0

我说叫一个接口:扇出使用异步中的WebAPI计算/等待

interface IExecutor { 
    String Name { get; } 
    Task<int> Execute(); 
} 

而且它的两个实现(细节是不相关的,你可以假设方法都标有异步和工作如预期) 。每个实现需要2-3秒的时间来运行,并将有2到5次执行IExecutor

我有一个控制器需要运行所有执行程序并将结果作为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应用的最佳实践。另外 - 给我想返回结果对象 - 其中结果需要一个执行器的名称和来自执行上述解决方案的int结果不作为for循环的外部工作我不再有权访问每个的名称属性遗嘱执行人。

那么,什么是这种方法的最佳实践(再 - 给一个Web API应用程序,而不是一个控制台应用程序)

+0

作为最佳实践,你应该命名为execute()方法ExecuteAsync() –

回答

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

如果我理解正确的话,你要找的somethng这样的:

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); 

OR,以下斯蒂芬显然建议:

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)) 
    ); 
+0

有一个编译错误:无法转换lambda表达式键入“System.Threading.Tasks.Task ”,因为它不是一个委托类型 –

+0

对不起。纠正。 –

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(); 
}